2008-11-05  Cameron Zwarich  <zwarich@apple.com>

        Rubber-stamped by Sam Weinig.

        Move more files to the runtime subdirectory of JavaScriptCore.

        JavaScriptCore:

        * API/APICast.h:
        * API/JSBase.cpp:
        * API/JSCallbackObject.cpp:
        * API/JSClassRef.cpp:
        * API/JSClassRef.h:
        * API/JSStringRefCF.cpp:
        * API/JSValueRef.cpp:
        * API/OpaqueJSString.cpp:
        * API/OpaqueJSString.h:
        * AllInOneFile.cpp:
        * GNUmakefile.am:
        * JavaScriptCore.pri:
        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
        * JavaScriptCore.xcodeproj/project.pbxproj:
        * JavaScriptCoreSources.bkl:
        * VM/CodeBlock.h:
        * VM/CodeGenerator.cpp:
        * VM/Machine.cpp:
        * VM/RegisterFile.h:
        * debugger/Debugger.h:
        * kjs/SourceProvider.h:
        * kjs/TypeInfo.h: Removed.
        * kjs/collector.cpp: Removed.
        * kjs/collector.h: Removed.
        * kjs/completion.h: Removed.
        * kjs/create_hash_table:
        * kjs/identifier.cpp: Removed.
        * kjs/identifier.h: Removed.
        * kjs/interpreter.cpp: Removed.
        * kjs/interpreter.h: Removed.
        * kjs/lexer.cpp:
        * kjs/lexer.h:
        * kjs/lookup.cpp: Removed.
        * kjs/lookup.h: Removed.
        * kjs/nodes.cpp:
        * kjs/nodes.h:
        * kjs/operations.cpp: Removed.
        * kjs/operations.h: Removed.
        * kjs/protect.h: Removed.
        * kjs/regexp.cpp: Removed.
        * kjs/regexp.h: Removed.
        * kjs/ustring.cpp: Removed.
        * kjs/ustring.h: Removed.
        * pcre/pcre_exec.cpp:
        * profiler/CallIdentifier.h:
        * profiler/Profile.h:
        * runtime/ArrayConstructor.cpp:
        * runtime/ArrayPrototype.cpp:
        * runtime/ArrayPrototype.h:
        * runtime/Collector.cpp: Copied from kjs/collector.cpp.
        * runtime/Collector.h: Copied from kjs/collector.h.
        * runtime/CollectorHeapIterator.h:
        * runtime/Completion.h: Copied from kjs/completion.h.
        * runtime/ErrorPrototype.cpp:
        * runtime/Identifier.cpp: Copied from kjs/identifier.cpp.
        * runtime/Identifier.h: Copied from kjs/identifier.h.
        * runtime/InitializeThreading.cpp:
        * runtime/Interpreter.cpp: Copied from kjs/interpreter.cpp.
        * runtime/Interpreter.h: Copied from kjs/interpreter.h.
        * runtime/JSCell.h:
        * runtime/JSGlobalData.cpp:
        * runtime/JSGlobalData.h:
        * runtime/JSLock.cpp:
        * runtime/JSNumberCell.cpp:
        * runtime/JSNumberCell.h:
        * runtime/JSObject.cpp:
        * runtime/JSValue.h:
        * runtime/Lookup.cpp: Copied from kjs/lookup.cpp.
        * runtime/Lookup.h: Copied from kjs/lookup.h.
        * runtime/MathObject.cpp:
        * runtime/NativeErrorPrototype.cpp:
        * runtime/NumberPrototype.cpp:
        * runtime/Operations.cpp: Copied from kjs/operations.cpp.
        * runtime/Operations.h: Copied from kjs/operations.h.
        * runtime/PropertyMapHashTable.h:
        * runtime/Protect.h: Copied from kjs/protect.h.
        * runtime/RegExp.cpp: Copied from kjs/regexp.cpp.
        * runtime/RegExp.h: Copied from kjs/regexp.h.
        * runtime/RegExpConstructor.cpp:
        * runtime/RegExpObject.h:
        * runtime/RegExpPrototype.cpp:
        * runtime/SmallStrings.h:
        * runtime/StringObjectThatMasqueradesAsUndefined.h:
        * runtime/StructureID.cpp:
        * runtime/StructureID.h:
        * runtime/StructureIDTransitionTable.h:
        * runtime/SymbolTable.h:
        * runtime/TypeInfo.h: Copied from kjs/TypeInfo.h.
        * runtime/UString.cpp: Copied from kjs/ustring.cpp.
        * runtime/UString.h: Copied from kjs/ustring.h.
        * wrec/CharacterClassConstructor.h:
        * wrec/WREC.h:

        WebCore:

        * ForwardingHeaders/kjs/collector.h: Removed.
        * ForwardingHeaders/kjs/completion.h: Removed.
        * ForwardingHeaders/kjs/identifier.h: Removed.
        * ForwardingHeaders/kjs/interpreter.h: Removed.
        * ForwardingHeaders/kjs/lookup.h: Removed.
        * ForwardingHeaders/kjs/operations.h: Removed.
        * ForwardingHeaders/kjs/protect.h: Removed.
        * ForwardingHeaders/kjs/ustring.h: Removed.
        * ForwardingHeaders/runtime/Collector.h: Copied from ForwardingHeaders/kjs/collector.h.
        * ForwardingHeaders/runtime/Completion.h: Copied from ForwardingHeaders/kjs/completion.h.
        * ForwardingHeaders/runtime/Identifier.h: Copied from ForwardingHeaders/kjs/identifier.h.
        * ForwardingHeaders/runtime/Interpreter.h: Copied from ForwardingHeaders/kjs/interpreter.h.
        * ForwardingHeaders/runtime/Lookup.h: Copied from ForwardingHeaders/kjs/lookup.h.
        * ForwardingHeaders/runtime/Operations.h: Copied from ForwardingHeaders/kjs/operations.h.
        * ForwardingHeaders/runtime/Protect.h: Copied from ForwardingHeaders/kjs/protect.h.
        * ForwardingHeaders/runtime/UString.h: Copied from ForwardingHeaders/kjs/ustring.h.
        * bindings/js/GCController.cpp:
        * bindings/js/JSCustomPositionCallback.h:
        * bindings/js/JSCustomPositionErrorCallback.h:
        * bindings/js/JSCustomSQLStatementCallback.h:
        * bindings/js/JSCustomSQLStatementErrorCallback.h:
        * bindings/js/JSCustomSQLTransactionErrorCallback.h:
        * bindings/js/JSCustomVoidCallback.h:
        * bindings/js/JSDOMBinding.h:
        * bindings/js/JSDOMWindowBase.h:
        * bindings/js/JSEventListener.h:
        * bindings/js/ScheduledAction.h:
        * bindings/js/ScriptController.cpp:
        * bindings/js/ScriptController.h:
        * bindings/objc/WebScriptObject.mm:
        * bindings/scripts/CodeGeneratorJS.pm:
        * bridge/NP_jsobject.cpp:
        * bridge/c/c_class.cpp:
        * bridge/jni/jni_class.cpp:
        * bridge/jni/jni_jsobject.mm:
        * bridge/npruntime.cpp:
        * bridge/runtime_root.h:
        * history/CachedPage.h:
        * html/CanvasRenderingContext2D.cpp:
        * html/HTMLCanvasElement.cpp:
        * inspector/InspectorController.cpp:
        * inspector/JavaScriptCallFrame.cpp:
        * page/Console.cpp:
        * page/Page.cpp:
        * platform/text/AtomicString.cpp:
        * platform/text/PlatformString.h:

        WebKit/mac:

        * ForwardingHeaders/kjs/collector.h: Removed.
        * ForwardingHeaders/kjs/identifier.h: Removed.
        * ForwardingHeaders/kjs/interpreter.h: Removed.
        * ForwardingHeaders/kjs/lookup.h: Removed.
        * ForwardingHeaders/kjs/operations.h: Removed.
        * ForwardingHeaders/kjs/protect.h: Removed.
        * ForwardingHeaders/runtime/Interpreter.h: Copied from ForwardingHeaders/kjs/interpreter.h.
        * WebView/WebScriptDebugDelegate.mm:

        WebKit/wx:

        * WebFrame.cpp:
        * WebView.cpp:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@38137 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/runtime/ArrayConstructor.cpp b/JavaScriptCore/runtime/ArrayConstructor.cpp
index 5784af0..a9949ba 100644
--- a/JavaScriptCore/runtime/ArrayConstructor.cpp
+++ b/JavaScriptCore/runtime/ArrayConstructor.cpp
@@ -26,7 +26,7 @@
 
 #include "ArrayPrototype.h"
 #include "JSArray.h"
-#include "lookup.h"
+#include "Lookup.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp
index 5280784..ecf9c19 100644
--- a/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -26,8 +26,8 @@
 
 #include "Machine.h"
 #include "ObjectPrototype.h"
-#include "lookup.h"
-#include "operations.h"
+#include "Lookup.h"
+#include "Operations.h"
 #include <algorithm>
 #include <wtf/Assertions.h>
 #include <wtf/HashSet.h>
diff --git a/JavaScriptCore/runtime/ArrayPrototype.h b/JavaScriptCore/runtime/ArrayPrototype.h
index 33ce30b..95f69c7 100644
--- a/JavaScriptCore/runtime/ArrayPrototype.h
+++ b/JavaScriptCore/runtime/ArrayPrototype.h
@@ -22,7 +22,7 @@
 #define ArrayPrototype_h
 
 #include "JSArray.h"
-#include "lookup.h"
+#include "Lookup.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp
new file mode 100644
index 0000000..67273cf
--- /dev/null
+++ b/JavaScriptCore/runtime/Collector.cpp
@@ -0,0 +1,1090 @@
+/*
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "Collector.h"
+
+#include "ArgList.h"
+#include "CollectorHeapIterator.h"
+#include "ExecState.h"
+#include "JSGlobalObject.h"
+#include "JSLock.h"
+#include "JSString.h"
+#include "JSValue.h"
+#include "Machine.h"
+#include "Tracing.h"
+#include <algorithm>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/HashCountedSet.h>
+#include <wtf/UnusedParam.h>
+
+#if PLATFORM(DARWIN)
+
+#include <mach/mach_port.h>
+#include <mach/mach_init.h>
+#include <mach/task.h>
+#include <mach/thread_act.h>
+#include <mach/vm_map.h>
+
+#elif PLATFORM(WIN_OS)
+
+#include <windows.h>
+
+#elif PLATFORM(UNIX)
+
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#if PLATFORM(SOLARIS)
+#include <thread.h>
+#endif
+
+#if PLATFORM(OPENBSD)
+#include <pthread.h>
+#endif
+
+#if HAVE(PTHREAD_NP_H)
+#include <pthread_np.h>
+#endif
+
+#endif
+
+#define DEBUG_COLLECTOR 0
+#define COLLECT_ON_EVERY_ALLOCATION 0
+
+using std::max;
+
+namespace JSC {
+
+// tunable parameters
+
+const size_t SPARE_EMPTY_BLOCKS = 2;
+const size_t GROWTH_FACTOR = 2;
+const size_t LOW_WATER_FACTOR = 4;
+const size_t ALLOCATIONS_PER_COLLECTION = 4000;
+// This value has to be a macro to be used in max() without introducing
+// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
+#define MIN_ARRAY_SIZE (static_cast<size_t>(14))
+
+static void freeHeap(CollectorHeap*);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+#if PLATFORM(DARWIN)
+typedef mach_port_t PlatformThread;
+#elif PLATFORM(WIN_OS)
+struct PlatformThread {
+    PlatformThread(DWORD _id, HANDLE _handle) : id(_id), handle(_handle) {}
+    DWORD id;
+    HANDLE handle;
+};
+#endif
+
+class Heap::Thread {
+public:
+    Thread(pthread_t pthread, const PlatformThread& platThread, void* base) 
+        : posixThread(pthread)
+        , platformThread(platThread)
+        , stackBase(base)
+    {
+    }
+
+    Thread* next;
+    pthread_t posixThread;
+    PlatformThread platformThread;
+    void* stackBase;
+};
+
+#endif
+
+Heap::Heap(JSGlobalData* globalData)
+    : m_markListSet(0)
+#if ENABLE(JSC_MULTIPLE_THREADS)
+    , m_registeredThreads(0)
+#endif
+    , m_globalData(globalData)
+{
+    ASSERT(globalData);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+    int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread);
+    if (error)
+        CRASH();
+#endif
+
+    memset(&primaryHeap, 0, sizeof(CollectorHeap));
+    memset(&numberHeap, 0, sizeof(CollectorHeap));
+}
+
+Heap::~Heap()
+{
+    // The destroy function must already have been called, so assert this.
+    ASSERT(!m_globalData);
+}
+
+void Heap::destroy()
+{
+    JSLock lock(false);
+
+    if (!m_globalData)
+        return;
+
+    // The global object is not GC protected at this point, so sweeping may delete it
+    // (and thus the global data) before other objects that may use the global data.
+    RefPtr<JSGlobalData> protect(m_globalData);
+
+    delete m_markListSet;
+    m_markListSet = 0;
+
+    sweep<PrimaryHeap>();
+    // No need to sweep number heap, because the JSNumber destructor doesn't do anything.
+
+    ASSERT(!primaryHeap.numLiveObjects);
+
+    freeHeap(&primaryHeap);
+    freeHeap(&numberHeap);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#ifndef NDEBUG
+    int error =
+#endif
+        pthread_key_delete(m_currentThreadRegistrar);
+    ASSERT(!error);
+
+    MutexLocker registeredThreadsLock(m_registeredThreadsMutex);
+    for (Heap::Thread* t = m_registeredThreads; t;) {
+        Heap::Thread* next = t->next;
+        delete t;
+        t = next;
+    }
+#endif
+
+    m_globalData = 0;
+}
+
+template <HeapType heapType>
+static NEVER_INLINE CollectorBlock* allocateBlock()
+{
+#if PLATFORM(DARWIN)
+    vm_address_t address = 0;
+    // FIXME: tag the region as a JavaScriptCore heap when we get a registered VM tag: <rdar://problem/6054788>.
+    vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
+#elif PLATFORM(WIN_OS)
+     // windows virtual address granularity is naturally 64k
+    LPVOID address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+#elif HAVE(POSIX_MEMALIGN)
+    void* address;
+    posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE);
+    memset(address, 0, BLOCK_SIZE);
+#else
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#error Need to initialize pagesize safely.
+#endif
+    static size_t pagesize = getpagesize();
+
+    size_t extra = 0;
+    if (BLOCK_SIZE > pagesize)
+        extra = BLOCK_SIZE - pagesize;
+
+    void* mmapResult = mmap(NULL, BLOCK_SIZE + extra, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+    uintptr_t address = reinterpret_cast<uintptr_t>(mmapResult);
+
+    size_t adjust = 0;
+    if ((address & BLOCK_OFFSET_MASK) != 0)
+        adjust = BLOCK_SIZE - (address & BLOCK_OFFSET_MASK);
+
+    if (adjust > 0)
+        munmap(reinterpret_cast<char*>(address), adjust);
+
+    if (adjust < extra)
+        munmap(reinterpret_cast<char*>(address + adjust + BLOCK_SIZE), extra - adjust);
+
+    address += adjust;
+    memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
+#endif
+    reinterpret_cast<CollectorBlock*>(address)->type = heapType;
+    return reinterpret_cast<CollectorBlock*>(address);
+}
+
+static void freeBlock(CollectorBlock* block)
+{
+#if PLATFORM(DARWIN)    
+    vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE);
+#elif PLATFORM(WIN_OS)
+    VirtualFree(block, 0, MEM_RELEASE);
+#elif HAVE(POSIX_MEMALIGN)
+    free(block);
+#else
+    munmap(reinterpret_cast<char*>(block), BLOCK_SIZE);
+#endif
+}
+
+static void freeHeap(CollectorHeap* heap)
+{
+    for (size_t i = 0; i < heap->usedBlocks; ++i)
+        if (heap->blocks[i])
+            freeBlock(heap->blocks[i]);
+    fastFree(heap->blocks);
+    memset(heap, 0, sizeof(CollectorHeap));
+}
+
+void Heap::recordExtraCost(size_t cost)
+{
+    // Our frequency of garbage collection tries to balance memory use against speed
+    // by collecting based on the number of newly created values. However, for values
+    // that hold on to a great deal of memory that's not in the form of other JS values,
+    // that is not good enough - in some cases a lot of those objects can pile up and
+    // use crazy amounts of memory without a GC happening. So we track these extra
+    // memory costs. Only unusually large objects are noted, and we only keep track
+    // of this extra cost until the next GC. In garbage collected languages, most values
+    // are either very short lived temporaries, or have extremely long lifetimes. So
+    // if a large value survives one garbage collection, there is not much point to
+    // collecting more frequently as long as it stays alive.
+    // NOTE: we target the primaryHeap unconditionally as JSNumber doesn't modify cost 
+
+    primaryHeap.extraCost += cost;
+}
+
+template <HeapType heapType> ALWAYS_INLINE void* Heap::heapAllocate(size_t s)
+{
+    typedef typename HeapConstants<heapType>::Block Block;
+    typedef typename HeapConstants<heapType>::Cell Cell;
+
+    CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
+    ASSERT(JSLock::lockCount() > 0);
+    ASSERT(JSLock::currentThreadIsHoldingLock());
+    ASSERT(s <= HeapConstants<heapType>::cellSize);
+    UNUSED_PARAM(s); // s is now only used for the above assert
+
+    ASSERT(heap.operationInProgress == NoOperation);
+    ASSERT(heapType == PrimaryHeap || heap.extraCost == 0);
+    // FIXME: If another global variable access here doesn't hurt performance
+    // too much, we could abort() in NDEBUG builds, which could help ensure we
+    // don't spend any time debugging cases where we allocate inside an object's
+    // deallocation code.
+
+    size_t numLiveObjects = heap.numLiveObjects;
+    size_t usedBlocks = heap.usedBlocks;
+    size_t i = heap.firstBlockWithPossibleSpace;
+
+#if COLLECT_ON_EVERY_ALLOCATION
+    collect();
+#endif
+
+    // if we have a huge amount of extra cost, we'll try to collect even if we still have
+    // free cells left.
+    if (heapType == PrimaryHeap && heap.extraCost > ALLOCATIONS_PER_COLLECTION) {
+        size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
+        size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
+        const size_t newCost = numNewObjects + heap.extraCost;
+        if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect)
+            goto collect;
+    }
+
+    ASSERT(heap.operationInProgress == NoOperation);
+#ifndef NDEBUG
+    // FIXME: Consider doing this in NDEBUG builds too (see comment above).
+    heap.operationInProgress = Allocation;
+#endif
+
+scan:
+    Block* targetBlock;
+    size_t targetBlockUsedCells;
+    if (i != usedBlocks) {
+        targetBlock = reinterpret_cast<Block*>(heap.blocks[i]);
+        targetBlockUsedCells = targetBlock->usedCells;
+        ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock);
+        while (targetBlockUsedCells == HeapConstants<heapType>::cellsPerBlock) {
+            if (++i == usedBlocks)
+                goto collect;
+            targetBlock = reinterpret_cast<Block*>(heap.blocks[i]);
+            targetBlockUsedCells = targetBlock->usedCells;
+            ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock);
+        }
+        heap.firstBlockWithPossibleSpace = i;
+    } else {
+
+collect:
+        size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
+        size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
+        const size_t newCost = numNewObjects + heap.extraCost;
+
+        if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect) {
+#ifndef NDEBUG
+            heap.operationInProgress = NoOperation;
+#endif
+            bool collected = collect();
+#ifndef NDEBUG
+            heap.operationInProgress = Allocation;
+#endif
+            if (collected) {
+                numLiveObjects = heap.numLiveObjects;
+                usedBlocks = heap.usedBlocks;
+                i = heap.firstBlockWithPossibleSpace;
+                goto scan;
+            }
+        }
+  
+        // didn't find a block, and GC didn't reclaim anything, need to allocate a new block
+        size_t numBlocks = heap.numBlocks;
+        if (usedBlocks == numBlocks) {
+            numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
+            heap.numBlocks = numBlocks;
+            heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*)));
+        }
+
+        targetBlock = reinterpret_cast<Block*>(allocateBlock<heapType>());
+        targetBlock->freeList = targetBlock->cells;
+        targetBlock->heap = this;
+        targetBlockUsedCells = 0;
+        heap.blocks[usedBlocks] = reinterpret_cast<CollectorBlock*>(targetBlock);
+        heap.usedBlocks = usedBlocks + 1;
+        heap.firstBlockWithPossibleSpace = usedBlocks;
+    }
+  
+    // find a free spot in the block and detach it from the free list
+    Cell* newCell = targetBlock->freeList;
+
+    // "next" field is a cell offset -- 0 means next cell, so a zeroed block is already initialized
+    targetBlock->freeList = (newCell + 1) + newCell->u.freeCell.next;
+
+    targetBlock->usedCells = static_cast<uint32_t>(targetBlockUsedCells + 1);
+    heap.numLiveObjects = numLiveObjects + 1;
+
+#ifndef NDEBUG
+    // FIXME: Consider doing this in NDEBUG builds too (see comment above).
+    heap.operationInProgress = NoOperation;
+#endif
+
+    return newCell;
+}
+
+void* Heap::allocate(size_t s)
+{
+    return heapAllocate<PrimaryHeap>(s);
+}
+
+void* Heap::allocateNumber(size_t s)
+{
+    return heapAllocate<NumberHeap>(s);
+}
+
+static inline void* currentThreadStackBase()
+{
+#if PLATFORM(DARWIN)
+    pthread_t thread = pthread_self();
+    return pthread_get_stackaddr_np(thread);
+#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(MSVC)
+    // offset 0x18 from the FS segment register gives a pointer to
+    // the thread information block for the current thread
+    NT_TIB* pTib;
+    __asm {
+        MOV EAX, FS:[18h]
+        MOV pTib, EAX
+    }
+    return static_cast<void*>(pTib->StackBase);
+#elif PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC)
+    PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
+    return reinterpret_cast<void*>(pTib->StackBase);
+#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(GCC)
+    // offset 0x18 from the FS segment register gives a pointer to
+    // the thread information block for the current thread
+    NT_TIB* pTib;
+    asm ( "movl %%fs:0x18, %0\n"
+          : "=r" (pTib)
+        );
+    return static_cast<void*>(pTib->StackBase);
+#elif PLATFORM(SOLARIS)
+    stack_t s;
+    thr_stksegment(&s);
+    return s.ss_sp;
+#elif PLATFORM(OPENBSD)
+    pthread_t thread = pthread_self();
+    stack_t stack;
+    pthread_stackseg_np(thread, &stack);
+    return stack.ss_sp;
+#elif PLATFORM(UNIX)
+    static void* stackBase = 0;
+    static size_t stackSize = 0;
+    static pthread_t stackThread;
+    pthread_t thread = pthread_self();
+    if (stackBase == 0 || thread != stackThread) {
+        pthread_attr_t sattr;
+        pthread_attr_init(&sattr);
+#if HAVE(PTHREAD_NP_H)
+        // e.g. on FreeBSD 5.4, neundorf@kde.org
+        pthread_attr_get_np(thread, &sattr);
+#else
+        // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
+        pthread_getattr_np(thread, &sattr);
+#endif
+        int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
+        (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
+        ASSERT(stackBase);
+        pthread_attr_destroy(&sattr);
+        stackThread = thread;
+    }
+    return static_cast<char*>(stackBase) + stackSize;
+#else
+#error Need a way to get the stack base on this platform
+#endif
+}
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+static inline PlatformThread getCurrentPlatformThread()
+{
+#if PLATFORM(DARWIN)
+    return pthread_mach_thread_np(pthread_self());
+#elif PLATFORM(WIN_OS)
+    HANDLE threadHandle = pthread_getw32threadhandle_np(pthread_self());
+    return PlatformThread(GetCurrentThreadId(), threadHandle);
+#endif
+}
+
+void Heap::registerThread()
+{
+    if (pthread_getspecific(m_currentThreadRegistrar))
+        return;
+
+    pthread_setspecific(m_currentThreadRegistrar, this);
+    Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), currentThreadStackBase());
+
+    MutexLocker lock(m_registeredThreadsMutex);
+
+    thread->next = m_registeredThreads;
+    m_registeredThreads = thread;
+}
+
+void Heap::unregisterThread(void* p)
+{
+    if (p)
+        static_cast<Heap*>(p)->unregisterThread();
+}
+
+void Heap::unregisterThread()
+{
+    pthread_t currentPosixThread = pthread_self();
+
+    MutexLocker lock(m_registeredThreadsMutex);
+
+    if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) {
+        Thread* t = m_registeredThreads;
+        m_registeredThreads = m_registeredThreads->next;
+        delete t;
+    } else {
+        Heap::Thread* last = m_registeredThreads;
+        Heap::Thread* t;
+        for (t = m_registeredThreads->next; t; t = t->next) {
+            if (pthread_equal(t->posixThread, currentPosixThread)) {
+                last->next = t->next;
+                break;
+            }
+            last = t;
+        }
+        ASSERT(t); // If t is NULL, we never found ourselves in the list.
+        delete t;
+    }
+}
+
+#else // ENABLE(JSC_MULTIPLE_THREADS)
+
+void Heap::registerThread()
+{
+}
+
+#endif
+
+#define IS_POINTER_ALIGNED(p) (((intptr_t)(p) & (sizeof(char*) - 1)) == 0)
+
+// cell size needs to be a power of two for this to be valid
+#define IS_HALF_CELL_ALIGNED(p) (((intptr_t)(p) & (CELL_MASK >> 1)) == 0)
+
+void Heap::markConservatively(void* start, void* end)
+{
+    if (start > end) {
+        void* tmp = start;
+        start = end;
+        end = tmp;
+    }
+
+    ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000);
+    ASSERT(IS_POINTER_ALIGNED(start));
+    ASSERT(IS_POINTER_ALIGNED(end));
+
+    char** p = static_cast<char**>(start);
+    char** e = static_cast<char**>(end);
+
+    size_t usedPrimaryBlocks = primaryHeap.usedBlocks;
+    size_t usedNumberBlocks = numberHeap.usedBlocks;
+    CollectorBlock** primaryBlocks = primaryHeap.blocks;
+    CollectorBlock** numberBlocks = numberHeap.blocks;
+
+    const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);
+
+    while (p != e) {
+        char* x = *p++;
+        if (IS_HALF_CELL_ALIGNED(x) && x) {
+            uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);
+            xAsBits &= CELL_ALIGN_MASK;
+            uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK;
+            CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset);
+            // Mark the the number heap, we can mark these Cells directly to avoid the virtual call cost
+            for (size_t block = 0; block < usedNumberBlocks; block++) {
+                if ((numberBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
+                    Heap::markCell(reinterpret_cast<JSCell*>(xAsBits));
+                    goto endMarkLoop;
+                }
+            }
+          
+            // Mark the primary heap
+            for (size_t block = 0; block < usedPrimaryBlocks; block++) {
+                if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
+                    if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree != 0) {
+                        JSCell* imp = reinterpret_cast<JSCell*>(xAsBits);
+                        if (!imp->marked())
+                            imp->mark();
+                    }
+                    break;
+                }
+            }
+        endMarkLoop:
+            ;
+        }
+    }
+}
+
+void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal()
+{
+    void* dummy;
+    void* stackPointer = &dummy;
+    void* stackBase = currentThreadStackBase();
+    markConservatively(stackPointer, stackBase);
+}
+
+void Heap::markCurrentThreadConservatively()
+{
+    // setjmp forces volatile registers onto the stack
+    jmp_buf registers;
+#if COMPILER(MSVC)
+#pragma warning(push)
+#pragma warning(disable: 4611)
+#endif
+    setjmp(registers);
+#if COMPILER(MSVC)
+#pragma warning(pop)
+#endif
+
+    markCurrentThreadConservativelyInternal();
+}
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+static inline void suspendThread(const PlatformThread& platformThread)
+{
+#if PLATFORM(DARWIN)
+    thread_suspend(platformThread);
+#elif PLATFORM(WIN_OS)
+    SuspendThread(platformThread.handle);
+#else
+#error Need a way to suspend threads on this platform
+#endif
+}
+
+static inline void resumeThread(const PlatformThread& platformThread)
+{
+#if PLATFORM(DARWIN)
+    thread_resume(platformThread);
+#elif PLATFORM(WIN_OS)
+    ResumeThread(platformThread.handle);
+#else
+#error Need a way to resume threads on this platform
+#endif
+}
+
+typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
+
+#if PLATFORM(DARWIN)
+
+#if PLATFORM(X86)
+typedef i386_thread_state_t PlatformThreadRegisters;
+#elif PLATFORM(X86_64)
+typedef x86_thread_state64_t PlatformThreadRegisters;
+#elif PLATFORM(PPC)
+typedef ppc_thread_state_t PlatformThreadRegisters;
+#elif PLATFORM(PPC64)
+typedef ppc_thread_state64_t PlatformThreadRegisters;
+#elif PLATFORM(ARM)
+typedef arm_thread_state_t PlatformThreadRegisters;
+#else
+#error Unknown Architecture
+#endif
+
+#elif PLATFORM(WIN_OS)&& PLATFORM(X86)
+typedef CONTEXT PlatformThreadRegisters;
+#else
+#error Need a thread register struct for this platform
+#endif
+
+size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
+{
+#if PLATFORM(DARWIN)
+
+#if PLATFORM(X86)
+    unsigned user_count = sizeof(regs)/sizeof(int);
+    thread_state_flavor_t flavor = i386_THREAD_STATE;
+#elif PLATFORM(X86_64)
+    unsigned user_count = x86_THREAD_STATE64_COUNT;
+    thread_state_flavor_t flavor = x86_THREAD_STATE64;
+#elif PLATFORM(PPC) 
+    unsigned user_count = PPC_THREAD_STATE_COUNT;
+    thread_state_flavor_t flavor = PPC_THREAD_STATE;
+#elif PLATFORM(PPC64)
+    unsigned user_count = PPC_THREAD_STATE64_COUNT;
+    thread_state_flavor_t flavor = PPC_THREAD_STATE64;
+#elif PLATFORM(ARM)
+    unsigned user_count = ARM_THREAD_STATE_COUNT;
+    thread_state_flavor_t flavor = ARM_THREAD_STATE;
+#else
+#error Unknown Architecture
+#endif
+
+    kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
+    if (result != KERN_SUCCESS) {
+        WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 
+                            "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
+        CRASH();
+    }
+    return user_count * sizeof(usword_t);
+// end PLATFORM(DARWIN)
+
+#elif PLATFORM(WIN_OS) && PLATFORM(X86)
+    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
+    GetThreadContext(platformThread.handle, &regs);
+    return sizeof(CONTEXT);
+#else
+#error Need a way to get thread registers on this platform
+#endif
+}
+
+static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
+{
+#if PLATFORM(DARWIN)
+
+#if __DARWIN_UNIX03
+
+#if PLATFORM(X86)
+    return reinterpret_cast<void*>(regs.__esp);
+#elif PLATFORM(X86_64)
+    return reinterpret_cast<void*>(regs.__rsp);
+#elif PLATFORM(PPC) || PLATFORM(PPC64)
+    return reinterpret_cast<void*>(regs.__r1);
+#elif PLATFORM(ARM)
+    return reinterpret_cast<void*>(regs.__sp);
+#else
+#error Unknown Architecture
+#endif
+
+#else // !__DARWIN_UNIX03
+
+#if PLATFORM(X86)
+    return reinterpret_cast<void*>(regs.esp);
+#elif PLATFORM(X86_64)
+    return reinterpret_cast<void*>(regs.rsp);
+#elif (PLATFORM(PPC) || PLATFORM(PPC64))
+    return reinterpret_cast<void*>(regs.r1);
+#else
+#error Unknown Architecture
+#endif
+
+#endif // __DARWIN_UNIX03
+
+// end PLATFORM(DARWIN)
+#elif PLATFORM(X86) && PLATFORM(WIN_OS)
+    return reinterpret_cast<void*>((uintptr_t) regs.Esp);
+#else
+#error Need a way to get the stack pointer for another thread on this platform
+#endif
+}
+
+void Heap::markOtherThreadConservatively(Thread* thread)
+{
+    suspendThread(thread->platformThread);
+
+    PlatformThreadRegisters regs;
+    size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
+
+    // mark the thread's registers
+    markConservatively(static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
+
+    void* stackPointer = otherThreadStackPointer(regs);
+    markConservatively(stackPointer, thread->stackBase);
+
+    resumeThread(thread->platformThread);
+}
+
+#endif
+
+void Heap::markStackObjectsConservatively()
+{
+    markCurrentThreadConservatively();
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+    if (m_currentThreadRegistrar) {
+
+        MutexLocker lock(m_registeredThreadsMutex);
+
+#ifndef NDEBUG
+        // Forbid malloc during the mark phase. Marking a thread suspends it, so 
+        // a malloc inside mark() would risk a deadlock with a thread that had been 
+        // suspended while holding the malloc lock.
+        fastMallocForbid();
+#endif
+        // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held,
+        // and since this is a shared heap, they are real locks.
+        for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
+            if (!pthread_equal(thread->posixThread, pthread_self()))
+                markOtherThreadConservatively(thread);
+        }
+#ifndef NDEBUG
+        fastMallocAllow();
+#endif
+    }
+#endif
+}
+
+void Heap::setGCProtectNeedsLocking()
+{
+    // Most clients do not need to call this, with the notable exception of WebCore.
+    // Clients that use shared heap have JSLock protection, while others are supposed
+    // to do explicit locking. WebCore violates this contract in Database code,
+    // which calls gcUnprotect from a secondary thread.
+    if (!m_protectedValuesMutex)
+        m_protectedValuesMutex.set(new Mutex);
+}
+
+void Heap::protect(JSValue* k)
+{
+    ASSERT(k);
+    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance);
+
+    if (JSImmediate::isImmediate(k))
+        return;
+
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->lock();
+
+    m_protectedValues.add(k->asCell());
+
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->unlock();
+}
+
+void Heap::unprotect(JSValue* k)
+{
+    ASSERT(k);
+    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance);
+
+    if (JSImmediate::isImmediate(k))
+        return;
+
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->lock();
+
+    m_protectedValues.remove(k->asCell());
+
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->unlock();
+}
+
+Heap* Heap::heap(JSValue* v)
+{
+    if (JSImmediate::isImmediate(v))
+        return 0;
+    return Heap::cellBlock(v->asCell())->heap;
+}
+
+void Heap::markProtectedObjects()
+{
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->lock();
+
+    ProtectCountSet::iterator end = m_protectedValues.end();
+    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
+        JSCell* val = it->first;
+        if (!val->marked())
+            val->mark();
+    }
+
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->unlock();
+}
+
+template <HeapType heapType> size_t Heap::sweep()
+{
+    typedef typename HeapConstants<heapType>::Block Block;
+    typedef typename HeapConstants<heapType>::Cell Cell;
+
+    // SWEEP: delete everything with a zero refcount (garbage) and unmark everything else
+    CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
+    
+    size_t emptyBlocks = 0;
+    size_t numLiveObjects = heap.numLiveObjects;
+    
+    for (size_t block = 0; block < heap.usedBlocks; block++) {
+        Block* curBlock = reinterpret_cast<Block*>(heap.blocks[block]);
+        
+        size_t usedCells = curBlock->usedCells;
+        Cell* freeList = curBlock->freeList;
+        
+        if (usedCells == HeapConstants<heapType>::cellsPerBlock) {
+            // special case with a block where all cells are used -- testing indicates this happens often
+            for (size_t i = 0; i < HeapConstants<heapType>::cellsPerBlock; i++) {
+                if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
+                    Cell* cell = curBlock->cells + i;
+                    
+                    if (heapType != NumberHeap) {
+                        JSCell* imp = reinterpret_cast<JSCell*>(cell);
+                        // special case for allocated but uninitialized object
+                        // (We don't need this check earlier because nothing prior this point 
+                        // assumes the object has a valid vptr.)
+                        if (cell->u.freeCell.zeroIfFree == 0)
+                            continue;
+                        
+                        imp->~JSCell();
+                    }
+                    
+                    --usedCells;
+                    --numLiveObjects;
+                    
+                    // put cell on the free list
+                    cell->u.freeCell.zeroIfFree = 0;
+                    cell->u.freeCell.next = freeList - (cell + 1);
+                    freeList = cell;
+                }
+            }
+        } else {
+            size_t minimumCellsToProcess = usedCells;
+            for (size_t i = 0; (i < minimumCellsToProcess) & (i < HeapConstants<heapType>::cellsPerBlock); i++) {
+                Cell* cell = curBlock->cells + i;
+                if (cell->u.freeCell.zeroIfFree == 0) {
+                    ++minimumCellsToProcess;
+                } else {
+                    if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
+                        if (heapType != NumberHeap) {
+                            JSCell* imp = reinterpret_cast<JSCell*>(cell);
+                            imp->~JSCell();
+                        }
+                        --usedCells;
+                        --numLiveObjects;
+                        
+                        // put cell on the free list
+                        cell->u.freeCell.zeroIfFree = 0;
+                        cell->u.freeCell.next = freeList - (cell + 1); 
+                        freeList = cell;
+                    }
+                }
+            }
+        }
+        
+        curBlock->usedCells = static_cast<uint32_t>(usedCells);
+        curBlock->freeList = freeList;
+        curBlock->marked.clearAll();
+        
+        if (usedCells == 0) {
+            emptyBlocks++;
+            if (emptyBlocks > SPARE_EMPTY_BLOCKS) {
+#if !DEBUG_COLLECTOR
+                freeBlock(reinterpret_cast<CollectorBlock*>(curBlock));
+#endif
+                // swap with the last block so we compact as we go
+                heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];
+                heap.usedBlocks--;
+                block--; // Don't move forward a step in this case
+                
+                if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) {
+                    heap.numBlocks = heap.numBlocks / GROWTH_FACTOR; 
+                    heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*)));
+                }
+            }
+        }
+    }
+    
+    if (heap.numLiveObjects != numLiveObjects)
+        heap.firstBlockWithPossibleSpace = 0;
+        
+    heap.numLiveObjects = numLiveObjects;
+    heap.numLiveObjectsAtLastCollect = numLiveObjects;
+    heap.extraCost = 0;
+    return numLiveObjects;
+}
+    
+bool Heap::collect()
+{
+#ifndef NDEBUG
+    if (m_globalData->isSharedInstance) {
+        ASSERT(JSLock::lockCount() > 0);
+        ASSERT(JSLock::currentThreadIsHoldingLock());
+    }
+#endif
+
+    ASSERT((primaryHeap.operationInProgress == NoOperation) | (numberHeap.operationInProgress == NoOperation));
+    if ((primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation))
+        abort();
+
+    JAVASCRIPTCORE_GC_BEGIN();
+    primaryHeap.operationInProgress = Collection;
+    numberHeap.operationInProgress = Collection;
+
+    // MARK: first mark all referenced objects recursively starting out from the set of root objects
+
+    markStackObjectsConservatively();
+    markProtectedObjects();
+    if (m_markListSet && m_markListSet->size())
+        ArgList::markLists(*m_markListSet);
+    if (m_globalData->exception && !m_globalData->exception->marked())
+        m_globalData->exception->mark();
+    m_globalData->machine->registerFile().markCallFrames(this);
+    m_globalData->smallStrings.mark();
+
+    JSGlobalObject* globalObject = m_globalData->head;
+    if (globalObject) {
+        do {
+            globalObject->markCrossHeapDependentObjects();
+            globalObject = globalObject->next();
+        } while (globalObject != m_globalData->head);
+    }
+
+    JAVASCRIPTCORE_GC_MARKED();
+
+    size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
+    size_t numLiveObjects = sweep<PrimaryHeap>();
+    numLiveObjects += sweep<NumberHeap>();
+
+    primaryHeap.operationInProgress = NoOperation;
+    numberHeap.operationInProgress = NoOperation;
+    JAVASCRIPTCORE_GC_END(originalLiveObjects, numLiveObjects);
+
+    return numLiveObjects < originalLiveObjects;
+}
+
+size_t Heap::size() 
+{
+    return primaryHeap.numLiveObjects + numberHeap.numLiveObjects; 
+}
+
+size_t Heap::globalObjectCount()
+{
+    size_t count = 0;
+    if (JSGlobalObject* head = m_globalData->head) {
+        JSGlobalObject* o = head;
+        do {
+            ++count;
+            o = o->next();
+        } while (o != head);
+    }
+    return count;
+}
+
+size_t Heap::protectedGlobalObjectCount()
+{
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->lock();
+
+    size_t count = 0;
+    if (JSGlobalObject* head = m_globalData->head) {
+        JSGlobalObject* o = head;
+        do {
+            if (m_protectedValues.contains(o))
+                ++count;
+            o = o->next();
+        } while (o != head);
+    }
+
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->unlock();
+
+    return count;
+}
+
+size_t Heap::protectedObjectCount()
+{
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->lock();
+
+    size_t result = m_protectedValues.size();
+
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->unlock();
+
+    return result;
+}
+
+static const char* typeName(JSCell* val)
+{
+    if (val->isString())
+        return "string";
+    if (val->isNumber())
+        return "number";
+    if (val->isGetterSetter())
+        return "gettersetter";
+    ASSERT(val->isObject());
+    const ClassInfo* info = static_cast<JSObject*>(val)->classInfo();
+    return info ? info->className : "Object";
+}
+
+HashCountedSet<const char*>* Heap::protectedObjectTypeCounts()
+{
+    HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
+
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->lock();
+
+    ProtectCountSet::iterator end = m_protectedValues.end();
+    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
+        counts->add(typeName(it->first));
+
+    if (m_protectedValuesMutex)
+        m_protectedValuesMutex->unlock();
+
+    return counts;
+}
+
+bool Heap::isBusy()
+{
+    return (primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation);
+}
+
+Heap::iterator Heap::primaryHeapBegin()
+{
+    return iterator(primaryHeap.blocks, primaryHeap.blocks + primaryHeap.usedBlocks);
+}
+
+Heap::iterator Heap::primaryHeapEnd()
+{
+    return iterator(primaryHeap.blocks + primaryHeap.usedBlocks, primaryHeap.blocks + primaryHeap.usedBlocks);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/Collector.h b/JavaScriptCore/runtime/Collector.h
new file mode 100644
index 0000000..4233b06
--- /dev/null
+++ b/JavaScriptCore/runtime/Collector.h
@@ -0,0 +1,279 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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 KJSCOLLECTOR_H_
+#define KJSCOLLECTOR_H_
+
+#include "JSImmediate.h"
+#include <string.h>
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Threading.h>
+
+// This is supremely lame that we require pthreads to build on windows.
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#include <pthread.h>
+#endif
+
+#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell)
+
+namespace JSC {
+
+    class ArgList;
+    class CollectorBlock;
+    class JSCell;
+    class JSGlobalData;
+
+    enum OperationInProgress { NoOperation, Allocation, Collection };
+    enum HeapType { PrimaryHeap, NumberHeap };
+
+    template <HeapType> class CollectorHeapIterator;
+
+    struct CollectorHeap {
+        CollectorBlock** blocks;
+        size_t numBlocks;
+        size_t usedBlocks;
+        size_t firstBlockWithPossibleSpace;
+
+        size_t numLiveObjects;
+        size_t numLiveObjectsAtLastCollect;
+        size_t extraCost;
+
+        OperationInProgress operationInProgress;
+    };
+
+    class Heap : Noncopyable {
+    public:
+        class Thread;
+        typedef CollectorHeapIterator<PrimaryHeap> iterator;
+
+        void destroy();
+
+#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+        // We can inline these functions because everything is compiled as
+        // one file, so the heapAllocate template definitions are available.
+        // However, allocateNumber is used via jsNumberCell outside JavaScriptCore.
+        // Thus allocateNumber needs to provide a non-inline version too.
+        void* inlineAllocateNumber(size_t s) { return heapAllocate<NumberHeap>(s); }
+        void* inlineAllocate(size_t s) { return heapAllocate<PrimaryHeap>(s); }
+#endif
+        void* allocateNumber(size_t);
+        void* allocate(size_t);
+
+        bool collect();
+        bool isBusy(); // true if an allocation or collection is in progress
+
+        static const size_t minExtraCostSize = 256;
+
+        void reportExtraMemoryCost(size_t cost);
+
+        size_t size();
+
+        void setGCProtectNeedsLocking();
+        void protect(JSValue*);
+        void unprotect(JSValue*);
+
+        static Heap* heap(JSValue*); // 0 for immediate values
+
+        size_t globalObjectCount();
+        size_t protectedObjectCount();
+        size_t protectedGlobalObjectCount();
+        HashCountedSet<const char*>* protectedObjectTypeCounts();
+
+        void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
+
+        static bool isCellMarked(const JSCell*);
+        static void markCell(JSCell*);
+
+        void markConservatively(void* start, void* end);
+
+        HashSet<ArgList*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<ArgList*>; return *m_markListSet; }
+
+        JSGlobalData* globalData() const { return m_globalData; }
+        static bool isNumber(JSCell*);
+        
+        // Iterators for the object heap.
+        iterator primaryHeapBegin();
+        iterator primaryHeapEnd();
+
+    private:
+        template <HeapType heapType> void* heapAllocate(size_t);
+        template <HeapType heapType> size_t sweep();
+        static CollectorBlock* cellBlock(const JSCell*);
+        static size_t cellOffset(const JSCell*);
+
+        friend class JSGlobalData;
+        Heap(JSGlobalData*);
+        ~Heap();
+
+        void recordExtraCost(size_t);
+        void markProtectedObjects();
+        void markCurrentThreadConservatively();
+        void markCurrentThreadConservativelyInternal();
+        void markOtherThreadConservatively(Thread*);
+        void markStackObjectsConservatively();
+
+        typedef HashCountedSet<JSCell*> ProtectCountSet;
+
+        CollectorHeap primaryHeap;
+        CollectorHeap numberHeap;
+
+        OwnPtr<Mutex> m_protectedValuesMutex; // Only non-null if the client explicitly requested it via setGCPrtotectNeedsLocking().
+        ProtectCountSet m_protectedValues;
+
+        HashSet<ArgList*>* m_markListSet;
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+        static void unregisterThread(void*);
+        void unregisterThread();
+
+        Mutex m_registeredThreadsMutex;
+        Thread* m_registeredThreads;
+        pthread_key_t m_currentThreadRegistrar;
+#endif
+
+        JSGlobalData* m_globalData;
+    };
+
+    // tunable parameters
+    template<size_t bytesPerWord> struct CellSize;
+
+    // cell size needs to be a power of two for certain optimizations in collector.cpp
+    template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; }; // 32-bit
+    template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; // 64-bit
+    const size_t BLOCK_SIZE = 16 * 4096; // 64k
+
+    // derived constants
+    const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
+    const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK;
+    const size_t MINIMUM_CELL_SIZE = CellSize<sizeof(void*)>::m_value;
+    const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
+    const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double);
+    const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
+    const size_t CELL_MASK = CELL_SIZE - 1;
+    const size_t CELL_ALIGN_MASK = ~CELL_MASK;
+    const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2);
+    const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK;
+    const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
+    const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
+  
+    struct CollectorBitmap {
+        uint32_t bits[BITMAP_WORDS];
+        bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } 
+        void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } 
+        void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } 
+        void clearAll() { memset(bits, 0, sizeof(bits)); }
+    };
+  
+    struct CollectorCell {
+        union {
+            double memory[CELL_ARRAY_LENGTH];
+            struct {
+                void* zeroIfFree;
+                ptrdiff_t next;
+            } freeCell;
+        } u;
+    };
+
+    struct SmallCollectorCell {
+        union {
+            double memory[CELL_ARRAY_LENGTH / 2];
+            struct {
+                void* zeroIfFree;
+                ptrdiff_t next;
+            } freeCell;
+        } u;
+    };
+
+    class CollectorBlock {
+    public:
+        CollectorCell cells[CELLS_PER_BLOCK];
+        uint32_t usedCells;
+        CollectorCell* freeList;
+        CollectorBitmap marked;
+        Heap* heap;
+        HeapType type;
+    };
+
+    class SmallCellCollectorBlock {
+    public:
+        SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK];
+        uint32_t usedCells;
+        SmallCollectorCell* freeList;
+        CollectorBitmap marked;
+        Heap* heap;
+        HeapType type;
+    };
+    
+    template <HeapType heapType> struct HeapConstants;
+
+    template <> struct HeapConstants<PrimaryHeap> {
+        static const size_t cellSize = CELL_SIZE;
+        static const size_t cellsPerBlock = CELLS_PER_BLOCK;
+        static const size_t bitmapShift = 0;
+        typedef CollectorCell Cell;
+        typedef CollectorBlock Block;
+    };
+
+    template <> struct HeapConstants<NumberHeap> {
+        static const size_t cellSize = SMALL_CELL_SIZE;
+        static const size_t cellsPerBlock = SMALL_CELLS_PER_BLOCK;
+        static const size_t bitmapShift = 1;
+        typedef SmallCollectorCell Cell;
+        typedef SmallCellCollectorBlock Block;
+    };
+
+    inline CollectorBlock* Heap::cellBlock(const JSCell* cell)
+    {
+        return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK);
+    }
+
+    inline bool Heap::isNumber(JSCell* cell)
+    {
+        return Heap::cellBlock(cell)->type == NumberHeap;
+    }
+
+    inline size_t Heap::cellOffset(const JSCell* cell)
+    {
+        return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
+    }
+
+    inline bool Heap::isCellMarked(const JSCell* cell)
+    {
+        return cellBlock(cell)->marked.get(cellOffset(cell));
+    }
+
+    inline void Heap::markCell(JSCell* cell)
+    {
+        cellBlock(cell)->marked.set(cellOffset(cell));
+    }
+
+    inline void Heap::reportExtraMemoryCost(size_t cost)
+    {
+        if (cost > minExtraCostSize) 
+            recordExtraCost(cost / (CELL_SIZE * 2)); 
+    }
+
+} // namespace JSC
+
+#endif /* KJSCOLLECTOR_H_ */
diff --git a/JavaScriptCore/runtime/CollectorHeapIterator.h b/JavaScriptCore/runtime/CollectorHeapIterator.h
index c5e1d78..c4b9dfc 100644
--- a/JavaScriptCore/runtime/CollectorHeapIterator.h
+++ b/JavaScriptCore/runtime/CollectorHeapIterator.h
@@ -24,7 +24,7 @@
  */
 
 #include "config.h"
-#include "collector.h"
+#include "Collector.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/Completion.h b/JavaScriptCore/runtime/Completion.h
new file mode 100644
index 0000000..56d13ed
--- /dev/null
+++ b/JavaScriptCore/runtime/Completion.h
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2003, 2007 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 KJS_COMPLETION_H
+#define KJS_COMPLETION_H
+
+#include "JSValue.h"
+
+namespace JSC {
+
+    enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted };
+
+    /*
+     * Completion objects are used to convey the return status and value
+     * from functions.
+     */
+    class Completion {
+    public:
+        Completion(ComplType type = Normal, JSValue* value = noValue())
+            : 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;
+    };
+
+} // namespace JSC
+
+#endif // KJS_COMPLETION_H
diff --git a/JavaScriptCore/runtime/ErrorPrototype.cpp b/JavaScriptCore/runtime/ErrorPrototype.cpp
index 69255c1..993f179 100644
--- a/JavaScriptCore/runtime/ErrorPrototype.cpp
+++ b/JavaScriptCore/runtime/ErrorPrototype.cpp
@@ -24,7 +24,7 @@
 #include "JSString.h"
 #include "ObjectPrototype.h"
 #include "PrototypeFunction.h"
-#include "ustring.h"
+#include "UString.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/Identifier.cpp b/JavaScriptCore/runtime/Identifier.cpp
new file mode 100644
index 0000000..50a6cc3
--- /dev/null
+++ b/JavaScriptCore/runtime/Identifier.cpp
@@ -0,0 +1,263 @@
+/*
+ *  Copyright (C) 2003, 2004, 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.
+ *
+ */
+
+#include "config.h"
+#include "identifier.h"
+
+#include "ExecState.h"
+#include <new> // for placement new
+#include <string.h> // for strlen
+#include <wtf/Assertions.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/HashSet.h>
+
+namespace JSC {
+
+typedef HashMap<const char*, RefPtr<UString::Rep>, PtrHash<const char*> > LiteralIdentifierTable;
+
+class IdentifierTable {
+public:
+    ~IdentifierTable()
+    {
+        HashSet<UString::Rep*>::iterator end = m_table.end();
+        for (HashSet<UString::Rep*>::iterator iter = m_table.begin(); iter != end; ++iter)
+            (*iter)->setIdentifierTable(0);
+    }
+    
+    std::pair<HashSet<UString::Rep*>::iterator, bool> add(UString::Rep* value)
+    {
+        std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add(value);
+        (*result.first)->setIdentifierTable(this);
+        return result;
+    }
+
+    template<typename U, typename V>
+    std::pair<HashSet<UString::Rep*>::iterator, bool> add(U value)
+    {
+        std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add<U, V>(value);
+        (*result.first)->setIdentifierTable(this);
+        return result;
+    }
+
+    void remove(UString::Rep* r) { m_table.remove(r); }
+
+    LiteralIdentifierTable& literalTable() { return m_literalTable; }
+
+private:
+    HashSet<UString::Rep*> m_table;
+    LiteralIdentifierTable m_literalTable;
+};
+
+IdentifierTable* createIdentifierTable()
+{
+    return new IdentifierTable;
+}
+
+void deleteIdentifierTable(IdentifierTable* table)
+{
+    delete table;
+}
+
+bool Identifier::equal(const UString::Rep* r, const char* s)
+{
+    int length = r->len;
+    const UChar* d = r->data();
+    for (int i = 0; i != length; ++i)
+        if (d[i] != (unsigned char)s[i])
+            return false;
+    return s[length] == 0;
+}
+
+bool Identifier::equal(const UString::Rep* r, const UChar* s, int length)
+{
+    if (r->len != length)
+        return false;
+    const UChar* d = r->data();
+    for (int i = 0; i != length; ++i)
+        if (d[i] != s[i])
+            return false;
+    return true;
+}
+
+struct CStringTranslator
+{
+    static unsigned hash(const char* c)
+    {
+        return UString::Rep::computeHash(c);
+    }
+
+    static bool equal(UString::Rep* r, const char* s)
+    {
+        return Identifier::equal(r, s);
+    }
+
+    static void translate(UString::Rep*& location, const char* c, unsigned hash)
+    {
+        size_t length = strlen(c);
+        UChar* d = static_cast<UChar*>(fastMalloc(sizeof(UChar) * length));
+        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
+        
+        UString::Rep* r = UString::Rep::create(d, static_cast<int>(length)).releaseRef();
+        r->rc = 0;
+        r->_hash = hash;
+
+        location = r;
+    }
+};
+
+PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c)
+{
+    if (!c) {
+        UString::Rep::null.hash();
+        return &UString::Rep::null;
+    }
+    if (!c[0]) {
+        UString::Rep::empty.hash();
+        return &UString::Rep::empty;
+    }
+    if (!c[1])
+        return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0])));
+
+    IdentifierTable& identifierTable = *globalData->identifierTable;
+    LiteralIdentifierTable& literalIdentifierTable = identifierTable.literalTable();
+
+    const LiteralIdentifierTable::iterator& iter = literalIdentifierTable.find(c);
+    if (iter != literalIdentifierTable.end())
+        return iter->second;
+
+    UString::Rep* addedString = *identifierTable.add<const char*, CStringTranslator>(c).first;
+    literalIdentifierTable.add(c, addedString);
+
+    return addedString;
+}
+
+PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const char* c)
+{
+    return add(&exec->globalData(), c);
+}
+
+struct UCharBuffer {
+    const UChar* s;
+    unsigned int length;
+};
+
+struct UCharBufferTranslator
+{
+    static unsigned hash(const UCharBuffer& buf)
+    {
+        return UString::Rep::computeHash(buf.s, buf.length);
+    }
+
+    static bool equal(UString::Rep* str, const UCharBuffer& buf)
+    {
+        return Identifier::equal(str, buf.s, buf.length);
+    }
+
+    static void translate(UString::Rep*& location, const UCharBuffer& buf, unsigned hash)
+    {
+        UChar* d = static_cast<UChar*>(fastMalloc(sizeof(UChar) * buf.length));
+        for (unsigned i = 0; i != buf.length; i++)
+            d[i] = buf.s[i];
+        
+        UString::Rep* r = UString::Rep::create(d, buf.length).releaseRef();
+        r->rc = 0;
+        r->_hash = hash;
+        
+        location = r; 
+    }
+};
+
+PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const UChar* s, int length)
+{
+    if (length == 1) {
+        UChar c = s[0];
+        if (c <= 0xFF)
+            return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
+    }
+    if (!length) {
+        UString::Rep::empty.hash();
+        return &UString::Rep::empty;
+    }
+    UCharBuffer buf = {s, length}; 
+    return *globalData->identifierTable->add<UCharBuffer, UCharBufferTranslator>(buf).first;
+}
+
+PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const UChar* s, int length)
+{
+    return add(&exec->globalData(), s, length);
+}
+
+PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UString::Rep* r)
+{
+    ASSERT(!r->identifierTable());
+    if (r->len == 1) {
+        UChar c = r->data()[0];
+        if (c <= 0xFF)
+            r = globalData->smallStrings.singleCharacterStringRep(c);
+            if (r->identifierTable()) {
+#ifndef NDEBUG
+                checkSameIdentifierTable(globalData, r);
+#endif
+                return r;
+            }
+    }
+    if (!r->len) {
+        UString::Rep::empty.hash();
+        return &UString::Rep::empty;
+    }
+    return *globalData->identifierTable->add(r).first;
+}
+
+PassRefPtr<UString::Rep> Identifier::addSlowCase(ExecState* exec, UString::Rep* r)
+{
+    return addSlowCase(&exec->globalData(), r);
+}
+
+void Identifier::remove(UString::Rep* r)
+{
+    r->identifierTable()->remove(r);
+}
+
+#ifndef NDEBUG
+
+void Identifier::checkSameIdentifierTable(ExecState* exec, UString::Rep* rep)
+{
+    ASSERT(rep->identifierTable() == exec->globalData().identifierTable);
+}
+
+void Identifier::checkSameIdentifierTable(JSGlobalData* globalData, UString::Rep* rep)
+{
+    ASSERT(rep->identifierTable() == globalData->identifierTable);
+}
+
+#else
+
+void Identifier::checkSameIdentifierTable(ExecState*, UString::Rep*)
+{
+}
+
+void Identifier::checkSameIdentifierTable(JSGlobalData*, UString::Rep*)
+{
+}
+
+#endif
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/Identifier.h b/JavaScriptCore/runtime/Identifier.h
new file mode 100644
index 0000000..9088d53
--- /dev/null
+++ b/JavaScriptCore/runtime/Identifier.h
@@ -0,0 +1,140 @@
+/*
+ *  Copyright (C) 2003, 2006, 2007 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 KJS_IDENTIFIER_H
+#define KJS_IDENTIFIER_H
+
+#include "JSGlobalData.h"
+#include "UString.h"
+
+namespace JSC {
+
+    class ExecState;
+
+    class Identifier {
+        friend class StructureID;
+    public:
+        Identifier() { }
+
+        Identifier(ExecState* exec, const char* s) : _ustring(add(exec, s)) { } // Only to be used with string literals.
+        Identifier(ExecState* exec, const UChar* s, int length) : _ustring(add(exec, s, length)) { }
+        Identifier(ExecState* exec, UString::Rep* rep) : _ustring(add(exec, rep)) { } 
+        Identifier(ExecState* exec, const UString& s) : _ustring(add(exec, s.rep())) { }
+
+        Identifier(JSGlobalData* globalData, const char* s) : _ustring(add(globalData, s)) { } // Only to be used with string literals.
+        Identifier(JSGlobalData* globalData, const UChar* s, int length) : _ustring(add(globalData, s, length)) { }
+        Identifier(JSGlobalData* globalData, UString::Rep* rep) : _ustring(add(globalData, rep)) { } 
+        Identifier(JSGlobalData* globalData, const UString& s) : _ustring(add(globalData, s.rep())) { }
+
+        // Special constructor for cases where we overwrite an object in place.
+        Identifier(PlacementNewAdoptType) : _ustring(PlacementNewAdopt) { }
+        
+        const UString& ustring() const { return _ustring; }
+        
+        const UChar* data() const { return _ustring.data(); }
+        int size() const { return _ustring.size(); }
+        
+        const char* ascii() const { return _ustring.ascii(); }
+        
+        static Identifier from(ExecState* exec, unsigned y) { return Identifier(exec, UString::from(y)); }
+        
+        bool isNull() const { return _ustring.isNull(); }
+        bool isEmpty() const { return _ustring.isEmpty(); }
+        
+        uint32_t toUInt32(bool* ok) const { return _ustring.toUInt32(ok); }
+        uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const { return _ustring.toUInt32(ok, tolerateEmptyString); };
+        uint32_t toStrictUInt32(bool* ok) const { return _ustring.toStrictUInt32(ok); }
+        unsigned toArrayIndex(bool* ok) const { return _ustring.toArrayIndex(ok); }
+        double toDouble() const { return _ustring.toDouble(); }
+        
+        friend bool operator==(const Identifier&, const Identifier&);
+        friend bool operator!=(const Identifier&, const Identifier&);
+
+        friend bool operator==(const Identifier&, const char*);
+    
+        static void remove(UString::Rep*);
+
+        static bool equal(const UString::Rep*, const char*);
+        static bool equal(const UString::Rep*, const UChar*, int length);
+        static bool equal(const UString::Rep* a, const UString::Rep* b) { return JSC::equal(a, b); }
+
+        static PassRefPtr<UString::Rep> add(ExecState*, const char*); // Only to be used with string literals.
+        static PassRefPtr<UString::Rep> add(JSGlobalData*, const char*); // Only to be used with string literals.
+
+        static void initializeIdentifierThreading();
+
+    private:
+        UString _ustring;
+        
+        static bool equal(const Identifier& a, const Identifier& b) { return a._ustring.rep() == b._ustring.rep(); }
+        static bool equal(const Identifier& a, const char* b) { return equal(a._ustring.rep(), b); }
+
+        static PassRefPtr<UString::Rep> add(ExecState*, const UChar*, int length);
+        static PassRefPtr<UString::Rep> add(JSGlobalData*, const UChar*, int length);
+
+        static PassRefPtr<UString::Rep> add(ExecState* exec, UString::Rep* r)
+        {
+            if (r->identifierTable()) {
+#ifndef NDEBUG
+                checkSameIdentifierTable(exec, r);
+#endif
+                return r;
+            }
+            return addSlowCase(exec, r);
+        }
+        static PassRefPtr<UString::Rep> add(JSGlobalData* globalData, UString::Rep* r)
+        {
+            if (r->identifierTable()) {
+#ifndef NDEBUG
+                checkSameIdentifierTable(globalData, r);
+#endif
+                return r;
+            }
+            return addSlowCase(globalData, r);
+        }
+
+        static PassRefPtr<UString::Rep> addSlowCase(ExecState*, UString::Rep* r);
+        static PassRefPtr<UString::Rep> addSlowCase(JSGlobalData*, UString::Rep* r);
+
+        static void checkSameIdentifierTable(ExecState*, UString::Rep*);
+        static void checkSameIdentifierTable(JSGlobalData*, UString::Rep*);
+    };
+    
+    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);
+    }
+
+    inline bool operator==(const Identifier& a, const char* b)
+    {
+        return Identifier::equal(a, b);
+    }
+
+    IdentifierTable* createIdentifierTable();
+    void deleteIdentifierTable(IdentifierTable*);
+
+} // namespace JSC
+
+#endif // KJS_IDENTIFIER_H
diff --git a/JavaScriptCore/runtime/InitializeThreading.cpp b/JavaScriptCore/runtime/InitializeThreading.cpp
index 9e14768..26bfb75 100644
--- a/JavaScriptCore/runtime/InitializeThreading.cpp
+++ b/JavaScriptCore/runtime/InitializeThreading.cpp
@@ -29,12 +29,12 @@
 #include "config.h"
 #include "InitializeThreading.h"
 
-#include "collector.h"
+#include "Collector.h"
 #include "DateMath.h"
 #include "dtoa.h"
 #include "identifier.h"
 #include "JSGlobalObject.h"
-#include "ustring.h"
+#include "UString.h"
 #include <wtf/Threading.h>
 
 namespace JSC {
diff --git a/JavaScriptCore/runtime/Interpreter.cpp b/JavaScriptCore/runtime/Interpreter.cpp
new file mode 100644
index 0000000..1188349
--- /dev/null
+++ b/JavaScriptCore/runtime/Interpreter.cpp
@@ -0,0 +1,78 @@
+/*
+ *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2003, 2007 Apple 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 "interpreter.h"
+
+#include "ExecState.h"
+#include "JSGlobalObject.h"
+#include "JSLock.h"
+#include "Machine.h"
+#include "Parser.h"
+#include "completion.h"
+#include "Debugger.h"
+#include <stdio.h>
+
+#if !PLATFORM(WIN_OS)
+#include <unistd.h>
+#endif
+
+namespace JSC {
+
+Completion Interpreter::checkSyntax(ExecState* exec, const SourceCode& source)
+{
+    JSLock lock(exec);
+
+    int errLine;
+    UString errMsg;
+
+    RefPtr<ProgramNode> progNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+    if (!progNode)
+        return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
+    return Completion(Normal);
+}
+
+Completion Interpreter::evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue* thisValue)
+{
+    JSLock lock(exec);
+    
+    int errLine;
+    UString errMsg;
+    RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+
+    if (!programNode)
+        return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
+
+    JSObject* thisObj = (!thisValue || thisValue->isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue->toObject(exec);
+
+    JSValue* exception = noValue();
+    JSValue* result = exec->machine()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception);
+
+    if (exception) {
+        if (exception->isObject() && asObject(exception)->isWatchdogException())
+            return Completion(Interrupted, result);
+        return Completion(Throw, exception);
+    }
+    return Completion(Normal, result);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/Interpreter.h b/JavaScriptCore/runtime/Interpreter.h
new file mode 100644
index 0000000..0366063
--- /dev/null
+++ b/JavaScriptCore/runtime/Interpreter.h
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2003, 2007 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 KJS_Interpreter_h
+#define KJS_Interpreter_h
+
+#include "JSValue.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC {
+
+  class Completion;
+  class ExecState;
+  class ScopeChain;
+  class SourceCode;
+  
+  class Interpreter {
+  public:
+    /**
+     * Parses the supplied ECMAScript code and checks for syntax errors.
+     *
+     * @param code The code to check
+     * @return A normal completion if there were no syntax errors in the code, 
+     * otherwise a throw completion with the syntax error as its value.
+     */
+    static Completion checkSyntax(ExecState*, const SourceCode&);
+
+    /**
+     * Evaluates the supplied ECMAScript code.
+     *
+     * Since this method returns a Completion, you should check the type of
+     * completion to detect an error or before attempting to access the returned
+     * value. For example, if an error occurs during script execution and is not
+     * caught by the script, the completion type will be Throw.
+     *
+     * If the supplied code is invalid, a SyntaxError will be thrown.
+     *
+     * @param code The code to evaluate
+     * @param thisValue The value to pass in as the "this" value for the script
+     * execution. This should either be jsNull() or an Object.
+     * @return A completion object representing the result of the execution.
+     */
+    static Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValue* thisValue = noValue());
+  };
+
+} // namespace JSC
+
+#endif // KJS_Interpreter_h
diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h
index 108dab6..8d8e30c 100644
--- a/JavaScriptCore/runtime/JSCell.h
+++ b/JavaScriptCore/runtime/JSCell.h
@@ -25,7 +25,7 @@
 
 #include "StructureID.h"
 #include "JSValue.h"
-#include "collector.h"
+#include "Collector.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp
index 8910679..bd725f5 100644
--- a/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -38,9 +38,9 @@
 #include "JSStaticScopeObject.h"
 #include "Machine.h"
 #include "Parser.h"
-#include "collector.h"
+#include "Collector.h"
 #include "lexer.h"
-#include "lookup.h"
+#include "Lookup.h"
 #include "nodes.h"
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h
index 3210149..814ff9d 100644
--- a/JavaScriptCore/runtime/JSGlobalData.h
+++ b/JavaScriptCore/runtime/JSGlobalData.h
@@ -32,7 +32,7 @@
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
-#include "collector.h"
+#include "Collector.h"
 #include "SmallStrings.h"
 
 struct OpaqueJSClass;
diff --git a/JavaScriptCore/runtime/JSLock.cpp b/JavaScriptCore/runtime/JSLock.cpp
index ee7fb3b..708553a 100644
--- a/JavaScriptCore/runtime/JSLock.cpp
+++ b/JavaScriptCore/runtime/JSLock.cpp
@@ -21,7 +21,7 @@
 #include "config.h"
 #include "JSLock.h"
 
-#include "collector.h"
+#include "Collector.h"
 #include "ExecState.h"
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
diff --git a/JavaScriptCore/runtime/JSNumberCell.cpp b/JavaScriptCore/runtime/JSNumberCell.cpp
index 5b3f3bd..0e33da6 100644
--- a/JavaScriptCore/runtime/JSNumberCell.cpp
+++ b/JavaScriptCore/runtime/JSNumberCell.cpp
@@ -24,7 +24,7 @@
 #include "JSNumberCell.h"
 
 #include "NumberObject.h"
-#include "ustring.h"
+#include "UString.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/JSNumberCell.h b/JavaScriptCore/runtime/JSNumberCell.h
index e2f6990..89fdf1b0 100644
--- a/JavaScriptCore/runtime/JSNumberCell.h
+++ b/JavaScriptCore/runtime/JSNumberCell.h
@@ -26,8 +26,8 @@
 #include "ExecState.h"
 #include "JSCell.h"
 #include "JSImmediate.h"
-#include "collector.h"
-#include "ustring.h"
+#include "Collector.h"
+#include "UString.h"
 #include <stddef.h> // for size_t
 
 namespace JSC {
diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp
index 82c1c63..897cf38 100644
--- a/JavaScriptCore/runtime/JSObject.cpp
+++ b/JavaScriptCore/runtime/JSObject.cpp
@@ -31,9 +31,9 @@
 #include "NativeErrorConstructor.h"
 #include "ObjectPrototype.h"
 #include "PropertyNameArray.h"
-#include "lookup.h"
+#include "Lookup.h"
 #include "nodes.h"
-#include "operations.h"
+#include "Operations.h"
 #include <math.h>
 #include <wtf/Assertions.h>
 
diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h
index 059a5e6..815a600 100644
--- a/JavaScriptCore/runtime/JSValue.h
+++ b/JavaScriptCore/runtime/JSValue.h
@@ -26,7 +26,7 @@
 #include "CallData.h"
 #include "ConstructData.h"
 #include "JSImmediate.h"
-#include "ustring.h"
+#include "UString.h"
 #include <stddef.h> // for size_t
 
 // The magic number 0x4000 is not important here, it is being subtracted back out (avoiding using zero since this
diff --git a/JavaScriptCore/runtime/Lookup.cpp b/JavaScriptCore/runtime/Lookup.cpp
new file mode 100644
index 0000000..b44b1e4
--- /dev/null
+++ b/JavaScriptCore/runtime/Lookup.cpp
@@ -0,0 +1,68 @@
+/*
+ *  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 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 "Lookup.h"
+
+#include "PrototypeFunction.h"
+
+namespace JSC {
+
+void HashTable::createTable(JSGlobalData* globalData) const
+{
+    ASSERT(!table);
+    HashEntry* entries = new HashEntry[hashSizeMask + 1];
+    for (int i = 0; i <= hashSizeMask; ++i)
+        entries[i].setKey(0);
+    for (int i = 0; values[i].key; ++i) {
+        UString::Rep* identifier = Identifier::add(globalData, values[i].key).releaseRef();
+        int hashIndex = identifier->computedHash() & hashSizeMask;
+        ASSERT(!entries[hashIndex].key());
+        entries[hashIndex].initialize(identifier, values[i].attributes, values[i].value1, values[i].value2);
+    }
+    table = entries;
+}
+
+void HashTable::deleteTable() const
+{
+    if (table) {
+        for (int i = 0; i != hashSizeMask + 1; ++i) {
+            if (UString::Rep* key = table[i].key())
+                key->deref();
+        }
+        delete [] table;
+        table = 0;
+    }
+}
+
+void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
+{
+    ASSERT(entry->attributes() & Function);
+    JSValue** location = thisObj->getDirectLocation(propertyName);
+
+    if (!location) {
+        PrototypeFunction* function = new (exec) PrototypeFunction(exec, entry->functionLength(), propertyName, entry->function());
+        thisObj->putDirect(propertyName, function, entry->attributes());
+        location = thisObj->getDirectLocation(propertyName);
+    }
+
+    slot.setValueSlot(thisObj, location, thisObj->offsetForLocation(location));
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/Lookup.h b/JavaScriptCore/runtime/Lookup.h
new file mode 100644
index 0000000..a547613
--- /dev/null
+++ b/JavaScriptCore/runtime/Lookup.h
@@ -0,0 +1,238 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2003, 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 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 KJS_lookup_h
+#define KJS_lookup_h
+
+#include "ExecState.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "PropertySlot.h"
+#include "identifier.h"
+#include <stdio.h>
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+    // Hash table generated by the create_hash_table script.
+    struct HashTableValue {
+        const char* key; // property name
+        unsigned char attributes; // JSObject attributes
+        intptr_t value1;
+        intptr_t value2;
+    };
+
+    // FIXME: There is no reason this get function can't be simpler.
+    // ie. typedef JSValue* (*GetFunction)(ExecState*, JSObject* baseObject)
+    typedef PropertySlot::GetValueFunc GetFunction;
+    typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue* value);
+
+    class HashEntry {
+    public:
+        void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2)
+        {
+            m_key = key;
+            m_attributes = attributes;
+            m_u.store.value1 = v1;
+            m_u.store.value2 = v2;
+        }
+
+        void setKey(UString::Rep* key) { m_key = key; }
+        UString::Rep* key() const { return m_key; }
+
+        unsigned char attributes() const { return m_attributes; }
+
+        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); }
+
+        GetFunction propertyGetter() const { ASSERT(!(m_attributes & Function)); return m_u.property.get; }
+        PutFunction propertyPutter() const { ASSERT(!(m_attributes & Function)); return m_u.property.put; }
+
+        intptr_t lexerValue() const { ASSERT(!m_attributes); return m_u.lexer.value; }
+
+    private:
+        UString::Rep* m_key;
+        unsigned char m_attributes; // JSObject attributes
+
+        union {
+            struct {
+                intptr_t value1;
+                intptr_t value2;
+            } store;
+            struct {
+                NativeFunction functionValue;
+                intptr_t length; // number of arguments for function
+            } function;
+            struct {
+                GetFunction get;
+                PutFunction put;
+            } property;
+            struct {
+                intptr_t value;
+                intptr_t unused;
+            } lexer;
+        } m_u;
+    };
+
+    struct HashTable {
+        int hashSizeMask; // Precomputed size for the hash table (minus 1).
+        const HashTableValue* values; // Fixed values generated by script.
+        mutable const HashEntry* table; // Table allocated at runtime.
+
+        ALWAYS_INLINE void initializeIfNeeded(JSGlobalData* globalData) const
+        {
+            if (!table)
+                createTable(globalData);
+        }
+
+        ALWAYS_INLINE void initializeIfNeeded(ExecState* exec) const
+        {
+            if (!table)
+                createTable(&exec->globalData());
+        }
+
+        void deleteTable() const;
+
+        // Find an entry in the table, and return the entry.
+        ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const
+        {
+            initializeIfNeeded(globalData);
+            return entry(identifier);
+        }
+
+        ALWAYS_INLINE const HashEntry* entry(ExecState* exec, const Identifier& identifier) const
+        {
+            initializeIfNeeded(exec);
+            return entry(identifier);
+        }
+
+    private:
+        ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const
+        {
+            ASSERT(table);
+            const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & hashSizeMask];
+            if (entry->key() != identifier.ustring().rep())
+                return 0;
+            return entry;
+        }
+
+        // Convert the hash table keys to identifiers.
+        void createTable(JSGlobalData*) const;
+    };
+
+    void setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
+
+    /**
+     * This method does it all (looking in the hashtable, checking for function
+     * overrides, creating the function or retrieving from cache, calling
+     * getValueProperty in case of a non-function property, forwarding to parent if
+     * unknown property).
+     */
+    template <class ThisImp, class ParentImp>
+    inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
+    {
+        const HashEntry* entry = table->entry(exec, propertyName);
+
+        if (!entry) // not found, forward to parent
+            return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
+
+        if (entry->attributes() & Function)
+            setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
+        else
+            slot.setCustom(thisObj, entry->propertyGetter());
+
+        return true;
+    }
+
+    /**
+     * Simplified version of getStaticPropertySlot in case there are only functions.
+     * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing
+     * a dummy getValueProperty.
+     */
+    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))
+            return true;
+
+        const HashEntry* entry = table->entry(exec, propertyName);
+        if (!entry)
+            return false;
+
+        setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
+        return true;
+    }
+
+    /**
+     * Simplified version of getStaticPropertySlot in case there are no functions, only "values".
+     * Using this instead of getStaticPropertySlot removes the need for a FuncImp class.
+     */
+    template <class ThisImp, class ParentImp>
+    inline bool getStaticValueSlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot)
+    {
+        const HashEntry* entry = table->entry(exec, propertyName);
+
+        if (!entry) // not found, forward to parent
+            return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
+
+        ASSERT(!(entry->attributes() & Function));
+
+        slot.setCustom(thisObj, entry->propertyGetter());
+        return true;
+    }
+
+    /**
+     * This one is for "put".
+     * It looks up a hash entry for the property to be set.  If an entry
+     * 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)
+    {
+        const HashEntry* entry = table->entry(exec, propertyName);
+
+        if (!entry)
+            return false;
+
+        if (entry->attributes() & Function) // function: put as override property
+            thisObj->putDirect(propertyName, value);
+        else if (!(entry->attributes() & ReadOnly))
+            entry->propertyPutter()(exec, thisObj, value);
+
+        return true;
+    }
+
+    /**
+     * This one is for "put".
+     * It calls lookupPut<ThisImp>() to set the value.  If that call
+     * returns false (meaning no entry in the hash table was found),
+     * then it calls put() on the ParentImp class.
+     */
+    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
+    }
+
+} // namespace JSC
+
+#endif // KJS_lookup_h
diff --git a/JavaScriptCore/runtime/MathObject.cpp b/JavaScriptCore/runtime/MathObject.cpp
index 8b972d3..ee7b700 100644
--- a/JavaScriptCore/runtime/MathObject.cpp
+++ b/JavaScriptCore/runtime/MathObject.cpp
@@ -22,7 +22,7 @@
 #include "MathObject.h"
 
 #include "ObjectPrototype.h"
-#include "operations.h"
+#include "Operations.h"
 #include <time.h>
 #include <wtf/Assertions.h>
 #include <wtf/MathExtras.h>
diff --git a/JavaScriptCore/runtime/NativeErrorPrototype.cpp b/JavaScriptCore/runtime/NativeErrorPrototype.cpp
index 9403aa9..df311d5 100644
--- a/JavaScriptCore/runtime/NativeErrorPrototype.cpp
+++ b/JavaScriptCore/runtime/NativeErrorPrototype.cpp
@@ -23,7 +23,7 @@
 
 #include "ErrorPrototype.h"
 #include "JSString.h"
-#include "ustring.h"
+#include "UString.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp
index d203e3f..4f5b4f9 100644
--- a/JavaScriptCore/runtime/NumberPrototype.cpp
+++ b/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -26,7 +26,7 @@
 #include "JSString.h"
 #include "PrototypeFunction.h"
 #include "dtoa.h"
-#include "operations.h"
+#include "Operations.h"
 #include <wtf/Assertions.h>
 #include <wtf/MathExtras.h>
 #include <wtf/Vector.h>
diff --git a/JavaScriptCore/runtime/Operations.cpp b/JavaScriptCore/runtime/Operations.cpp
new file mode 100644
index 0000000..a857bf2
--- /dev/null
+++ b/JavaScriptCore/runtime/Operations.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * 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 "Operations.h"
+
+#include "Error.h"
+#include "JSObject.h"
+#include "JSString.h"
+#include <math.h>
+#include <stdio.h>
+#include <wtf/MathExtras.h>
+
+#if HAVE(FLOAT_H)
+#include <float.h>
+#endif
+
+namespace JSC {
+
+// ECMA 11.9.3
+bool equal(ExecState* exec, JSValue* v1, JSValue* v2)
+{
+    if (JSImmediate::areBothImmediateNumbers(v1, v2))
+        return v1 == v2;
+
+    return equalSlowCaseInline(exec, v1, v2);
+}
+
+bool equalSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
+{
+    return equalSlowCaseInline(exec, v1, v2);
+}
+
+bool strictEqual(JSValue* v1, JSValue* v2)
+{
+    if (JSImmediate::areBothImmediate(v1, v2))
+        return v1 == v2;
+
+    if (JSImmediate::isEitherImmediate(v1, v2) & (v1 != JSImmediate::from(0)) & (v2 != JSImmediate::from(0)))
+        return false;
+
+    return strictEqualSlowCaseInline(v1, v2);
+}
+
+bool strictEqualSlowCase(JSValue* v1, JSValue* v2)
+{
+    return strictEqualSlowCaseInline(v1, v2);
+}
+
+NEVER_INLINE JSValue* throwOutOfMemoryError(ExecState* exec)
+{
+    JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+    exec->setException(error);
+    return error;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h
new file mode 100644
index 0000000..fad9720
--- /dev/null
+++ b/JavaScriptCore/runtime/Operations.h
@@ -0,0 +1,137 @@
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.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 _KJS_OPERATIONS_H_
+#define _KJS_OPERATIONS_H_
+
+#include "JSImmediate.h"
+#include "JSNumberCell.h"
+#include "JSString.h"
+
+namespace JSC {
+
+  // ECMA 11.9.3
+  bool equal(ExecState*, JSValue*, JSValue*);
+  bool equalSlowCase(ExecState*, JSValue*, JSValue*);
+
+  ALWAYS_INLINE bool equalSlowCaseInline(ExecState* exec, JSValue* v1, JSValue* v2)
+  {
+      ASSERT(!JSImmediate::areBothImmediateNumbers(v1, v2));
+
+      do {
+          if (v1->isNumber() && v2->isNumber())
+              return v1->uncheckedGetNumber() == v2->uncheckedGetNumber();
+
+          bool s1 = v1->isString();
+          bool s2 = v2->isString();
+          if (s1 && s2)
+              return asString(v1)->value() == asString(v2)->value();
+
+          if (v1->isUndefinedOrNull()) {
+              if (v2->isUndefinedOrNull())
+                  return true;
+              if (JSImmediate::isImmediate(v2))
+                  return false;
+              return v2->asCell()->structureID()->typeInfo().masqueradesAsUndefined();
+          }
+
+          if (v2->isUndefinedOrNull()) {
+              if (JSImmediate::isImmediate(v1))
+                  return false;
+              return v1->asCell()->structureID()->typeInfo().masqueradesAsUndefined();
+          }
+
+          if (v1->isObject()) {
+              if (v2->isObject())
+                  return v1 == v2;
+              JSValue* p1 = v1->toPrimitive(exec);
+              if (exec->hadException())
+                  return false;
+              v1 = p1;
+              if (JSImmediate::areBothImmediateNumbers(v1, v2))
+                  return v1 == v2;
+              continue;
+          }
+
+          if (v2->isObject()) {
+              JSValue* p2 = v2->toPrimitive(exec);
+              if (exec->hadException())
+                  return false;
+              v2 = p2;
+              if (JSImmediate::areBothImmediateNumbers(v1, v2))
+                  return v1 == v2;
+              continue;
+          }
+
+          if (s1 || s2) {
+              double d1 = v1->toNumber(exec);
+              double d2 = v2->toNumber(exec);
+              return d1 == d2;
+          }
+
+          if (v1->isBoolean()) {
+              if (v2->isNumber())
+                  return static_cast<double>(v1->getBoolean()) == v2->uncheckedGetNumber();
+          } else if (v2->isBoolean()) {
+              if (v1->isNumber())
+                  return v1->uncheckedGetNumber() == static_cast<double>(v2->getBoolean());
+          }
+
+          return v1 == v2;
+      } while (true);
+  }
+
+
+  bool strictEqual(JSValue*, JSValue*);
+  bool strictEqualSlowCase(JSValue*, JSValue*);
+
+  inline bool strictEqualSlowCaseInline(JSValue* v1, JSValue* v2)
+  {
+      ASSERT(!JSImmediate::areBothImmediate(v1, v2));
+      
+      if (JSImmediate::isEitherImmediate(v1, v2)) {
+          ASSERT(v1 == JSImmediate::zeroImmediate() || v2 == JSImmediate::zeroImmediate());
+          ASSERT(v1 != v2);
+
+          // The reason we can't just return false here is that 0 === -0,
+          // and while the former is an immediate number, the latter is not.
+          if (v1 == JSImmediate::zeroImmediate())
+              return asCell(v2)->isNumber() && asNumberCell(v2)->value() == 0;
+          return asCell(v1)->isNumber() && asNumberCell(v1)->value() == 0;
+      }
+      
+      if (asCell(v1)->isNumber()) {
+          return asCell(v2)->isNumber()
+              && asNumberCell(v1)->value() == asNumberCell(v2)->value();
+      }
+
+      if (asCell(v1)->isString()) {
+          return asCell(v2)->isString()
+              && asString(v1)->value() == asString(v2)->value();
+      }
+
+      return v1 == v2;
+  }
+
+  JSValue* throwOutOfMemoryError(ExecState*);
+}
+
+#endif
diff --git a/JavaScriptCore/runtime/PropertyMapHashTable.h b/JavaScriptCore/runtime/PropertyMapHashTable.h
index 98b0727..0d6c521 100644
--- a/JavaScriptCore/runtime/PropertyMapHashTable.h
+++ b/JavaScriptCore/runtime/PropertyMapHashTable.h
@@ -21,7 +21,7 @@
 #ifndef PropertyMapHashTable_h
 #define PropertyMapHashTable_h
 
-#include "ustring.h"
+#include "UString.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/Protect.h b/JavaScriptCore/runtime/Protect.h
new file mode 100644
index 0000000..9a406bf
--- /dev/null
+++ b/JavaScriptCore/runtime/Protect.h
@@ -0,0 +1,154 @@
+/*
+ *  Copyright (C) 2004, 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 protect_h
+#define protect_h
+
+#include "JSCell.h"
+#include "Collector.h"
+
+namespace JSC {
+
+    inline void gcProtect(JSCell* val) 
+    {
+        Heap::heap(val)->protect(val);
+    }
+
+    inline void gcUnprotect(JSCell* val)
+    {
+        Heap::heap(val)->unprotect(val);
+    }
+
+    inline void gcProtectNullTolerant(JSCell* val) 
+    {
+        if (val) 
+            gcProtect(val);
+    }
+
+    inline void gcUnprotectNullTolerant(JSCell* val) 
+    {
+        if (val) 
+            gcUnprotect(val);
+    }
+    
+    inline void gcProtect(JSValue* value)
+    {
+        if (JSImmediate::isImmediate(value))
+            return;
+        gcProtect(asCell(value));
+    }
+
+    inline void gcUnprotect(JSValue* value)
+    {
+        if (JSImmediate::isImmediate(value))
+            return;
+        gcUnprotect(asCell(value));
+    }
+
+    inline void gcProtectNullTolerant(JSValue* value)
+    {
+        if (!value || JSImmediate::isImmediate(value))
+            return;
+        gcProtect(asCell(value));
+    }
+
+    inline void gcUnprotectNullTolerant(JSValue* value)
+    {
+        if (!value || JSImmediate::isImmediate(value))
+            return;
+        gcUnprotect(asCell(value));
+    }
+
+    // FIXME: Share more code with RefPtr template? The only differences are the ref/deref operation
+    // and the implicit conversion to raw pointer
+    template <class T> class ProtectedPtr {
+    public:
+        ProtectedPtr() : m_ptr(0) { }
+        ProtectedPtr(T* ptr);
+        ProtectedPtr(const ProtectedPtr&);
+        ~ProtectedPtr();
+
+        template <class U> ProtectedPtr(const ProtectedPtr<U>&);
+        
+        T* get() const { return m_ptr; }
+        operator T*() const { return m_ptr; }
+        T* operator->() const { return m_ptr; }
+        
+        bool operator!() const { return !m_ptr; }
+
+        ProtectedPtr& operator=(const ProtectedPtr&);
+        ProtectedPtr& operator=(T*);
+        
+    private:
+        T* m_ptr;
+    };
+
+    template <class T> ProtectedPtr<T>::ProtectedPtr(T* ptr)
+        : m_ptr(ptr)
+    {
+        gcProtectNullTolerant(m_ptr);
+    }
+
+    template <class T> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr& o)
+        : m_ptr(o.get())
+    {
+        gcProtectNullTolerant(m_ptr);
+    }
+
+    template <class T> ProtectedPtr<T>::~ProtectedPtr()
+    {
+        gcUnprotectNullTolerant(m_ptr);
+    }
+
+    template <class T> template <class U> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U>& o)
+        : m_ptr(o.get())
+    {
+        gcProtectNullTolerant(m_ptr);
+    }
+
+    template <class T> ProtectedPtr<T>& ProtectedPtr<T>::operator=(const ProtectedPtr<T>& o) 
+    {
+        T* optr = o.m_ptr;
+        gcProtectNullTolerant(optr);
+        gcUnprotectNullTolerant(m_ptr);
+        m_ptr = optr;
+        return *this;
+    }
+
+    template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(T* optr)
+    {
+        gcProtectNullTolerant(optr);
+        gcUnprotectNullTolerant(m_ptr);
+        m_ptr = optr;
+        return *this;
+    }
+
+    template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() == b.get(); }
+    template <class T> inline bool operator==(const ProtectedPtr<T>& a, const T* b) { return a.get() == b; }
+    template <class T> inline bool operator==(const T* a, const ProtectedPtr<T>& b) { return a == b.get(); }
+
+    template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() != b.get(); }
+    template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const T* b) { return a.get() != b; }
+    template <class T> inline bool operator!=(const T* a, const ProtectedPtr<T>& b) { return a != b.get(); }
+ 
+} // namespace JSC
+
+#endif // protect_h
diff --git a/JavaScriptCore/runtime/RegExp.cpp b/JavaScriptCore/runtime/RegExp.cpp
new file mode 100644
index 0000000..661a1c7
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExp.cpp
@@ -0,0 +1,182 @@
+/*
+ *  Copyright (C) 1999-2001, 2004 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
+ *
+ */
+
+#include "config.h"
+#include "RegExp.h"
+
+#include "CTI.h"
+#include "lexer.h"
+#include <pcre/pcre.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wrec/WREC.h>
+#include <wtf/Assertions.h>
+#include <wtf/OwnArrayPtr.h>
+
+namespace JSC {
+
+inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern)
+    : m_pattern(pattern)
+    , m_flagBits(0)
+    , m_regExp(0)
+    , m_constructionError(0)
+    , m_numSubpatterns(0)
+{
+#if ENABLE(WREC)
+    m_wrecFunction = CTI::compileRegExp(globalData->machine, pattern, &m_numSubpatterns, &m_constructionError);
+    if (m_wrecFunction)
+        return;
+    // Fall through to non-WREC case.
+#else
+    UNUSED_PARAM(globalData);
+#endif
+    m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
+        JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, &m_numSubpatterns, &m_constructionError);
+}
+
+PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern)
+{
+    return adoptRef(new RegExp(globalData, pattern));
+}
+
+inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
+    : m_pattern(pattern)
+    , m_flags(flags)
+    , m_flagBits(0)
+    , m_regExp(0)
+    , m_constructionError(0)
+    , m_numSubpatterns(0)
+{
+    // NOTE: The global flag is handled on a case-by-case basis by functions like
+    // String::match and RegExpObject::match.
+    if (flags.find('g') != -1)
+        m_flagBits |= Global;
+
+    // FIXME: Eliminate duplication by adding a way ask a JSRegExp what its flags are?
+    JSRegExpIgnoreCaseOption ignoreCaseOption = JSRegExpDoNotIgnoreCase;
+    if (flags.find('i') != -1) {
+        m_flagBits |= IgnoreCase;
+        ignoreCaseOption = JSRegExpIgnoreCase;
+    }
+
+    JSRegExpMultilineOption multilineOption = JSRegExpSingleLine;
+    if (flags.find('m') != -1) {
+        m_flagBits |= Multiline;
+        multilineOption = JSRegExpMultiline;
+    }
+
+#if ENABLE(WREC)
+    m_wrecFunction = CTI::compileRegExp(globalData->machine, pattern, &m_numSubpatterns, &m_constructionError, (m_flagBits & IgnoreCase), (m_flagBits & Multiline));
+    if (m_wrecFunction)
+        return;
+    // Fall through to non-WREC case.
+#else
+    UNUSED_PARAM(globalData);
+#endif
+    m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
+        ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
+}
+
+PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags)
+{
+    return adoptRef(new RegExp(globalData, pattern, flags));
+}
+
+RegExp::~RegExp()
+{
+    jsRegExpFree(m_regExp);
+#if ENABLE(WREC)
+    if (m_wrecFunction)
+        WTF::fastFreeExecutable(m_wrecFunction);
+#endif
+}
+
+int RegExp::match(const UString& s, int i, OwnArrayPtr<int>* ovector)
+{
+    if (i < 0)
+        i = 0;
+    if (ovector)
+        ovector->clear();
+
+    if (i > s.size() || s.isNull())
+        return -1;
+
+#if ENABLE(WREC)
+    if (m_wrecFunction) {
+        int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+        int* offsetVector = new int [offsetVectorSize];
+        for (int j = 0; j < offsetVectorSize; ++j)
+            offsetVector[j] = -1;
+
+        OwnArrayPtr<int> nonReturnedOvector;
+        if (!ovector)
+            nonReturnedOvector.set(offsetVector);
+        else
+            ovector->set(offsetVector);
+
+        int result = reinterpret_cast<WRECFunction>(m_wrecFunction)(s.data(), i, s.size(), offsetVector);
+
+        if (result < 0) {
+#ifndef NDEBUG
+            // TODO: define up a symbol, rather than magic -1
+            if (result != -1)
+                fprintf(stderr, "jsRegExpExecute failed with result %d\n", result);
+#endif
+            if (ovector)
+                ovector->clear();
+        }
+        return result;
+    } else
+#endif
+    if (m_regExp) {
+        // Set up the offset vector for the result.
+        // First 2/3 used for result, the last third used by PCRE.
+        int* offsetVector;
+        int offsetVectorSize;
+        int fixedSizeOffsetVector[3];
+        if (!ovector) {
+            offsetVectorSize = 3;
+            offsetVector = fixedSizeOffsetVector;
+        } else {
+            offsetVectorSize = (m_numSubpatterns + 1) * 3;
+            offsetVector = new int [offsetVectorSize];
+            ovector->set(offsetVector);
+        }
+
+        int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), i, offsetVector, offsetVectorSize);
+    
+        if (numMatches < 0) {
+#ifndef NDEBUG
+            if (numMatches != JSRegExpErrorNoMatch)
+                fprintf(stderr, "jsRegExpExecute failed with result %d\n", numMatches);
+#endif
+            if (ovector)
+                ovector->clear();
+            return -1;
+        }
+
+        return offsetVector[0];
+    }
+
+    return -1;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/RegExp.h b/JavaScriptCore/runtime/RegExp.h
new file mode 100644
index 0000000..2abb805
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExp.h
@@ -0,0 +1,76 @@
+/*
+ *  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 KJS_REGEXP_H
+#define KJS_REGEXP_H
+
+#include "UString.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+
+struct JSRegExp;
+
+namespace JSC {
+
+    class JSGlobalData;
+
+    class RegExp : public RefCounted<RegExp> {
+    public:
+        static PassRefPtr<RegExp> create(JSGlobalData*, const UString& pattern);
+        static PassRefPtr<RegExp> create(JSGlobalData*, const UString& pattern, const UString& flags);
+        ~RegExp();
+
+        bool global() const { return m_flagBits & Global; }
+        bool ignoreCase() const { return m_flagBits & IgnoreCase; }
+        bool multiline() const { return m_flagBits & Multiline; }
+
+        const UString& pattern() const { return m_pattern; }
+        const UString& flags() const { return m_flags; }
+
+        bool isValid() const { return !m_constructionError; }
+        const char* errorMessage() const { return m_constructionError; }
+
+        int match(const UString&, int offset, OwnArrayPtr<int>* ovector = 0);
+        unsigned numSubpatterns() const { return m_numSubpatterns; }
+
+    private:
+        RegExp(JSGlobalData*, const UString& pattern);
+        RegExp(JSGlobalData*, const UString& pattern, const UString& flags);
+
+        void compile();
+
+        enum FlagBits { Global = 1, IgnoreCase = 2, Multiline = 4 };
+
+        UString m_pattern; // FIXME: Just decompile m_regExp instead of storing this.
+        UString m_flags; // FIXME: Just decompile m_regExp instead of storing this.
+        int m_flagBits;
+        JSRegExp* m_regExp;
+        const char* m_constructionError;
+        unsigned m_numSubpatterns;
+
+#if ENABLE(WREC)
+        // Called as a WRECFunction
+        void* m_wrecFunction;
+#endif
+    };
+
+} // namespace JSC
+
+#endif // KJS_REGEXP_H
diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp
index 4c4db39..6e3b90cd 100644
--- a/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -29,7 +29,7 @@
 #include "RegExpMatchesArray.h"
 #include "RegExpObject.h"
 #include "RegExpPrototype.h"
-#include "regexp.h"
+#include "RegExp.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/RegExpObject.h b/JavaScriptCore/runtime/RegExpObject.h
index d80b47c..d5bf225 100644
--- a/JavaScriptCore/runtime/RegExpObject.h
+++ b/JavaScriptCore/runtime/RegExpObject.h
@@ -22,7 +22,7 @@
 #define RegExpObject_h
 
 #include "JSObject.h"
-#include "regexp.h"
+#include "RegExp.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp
index ceee32a..6514ad6 100644
--- a/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -29,7 +29,7 @@
 #include "ObjectPrototype.h"
 #include "PrototypeFunction.h"
 #include "RegExpObject.h"
-#include "regexp.h"
+#include "RegExp.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/SmallStrings.h b/JavaScriptCore/runtime/SmallStrings.h
index 7c71208..7e5f5c8 100644
--- a/JavaScriptCore/runtime/SmallStrings.h
+++ b/JavaScriptCore/runtime/SmallStrings.h
@@ -26,7 +26,7 @@
 #ifndef SmallStrings_h
 #define SmallStrings_h
 
-#include "ustring.h"
+#include "UString.h"
 #include <wtf/OwnPtr.h>
 
 namespace JSC {
diff --git a/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
index d703228..fad3852 100644
--- a/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
+++ b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
@@ -23,7 +23,7 @@
 
 #include "JSGlobalObject.h"
 #include "StringObject.h"
-#include "ustring.h"
+#include "UString.h"
 
 namespace JSC {
 
diff --git a/JavaScriptCore/runtime/StructureID.cpp b/JavaScriptCore/runtime/StructureID.cpp
index 8333595..95da830 100644
--- a/JavaScriptCore/runtime/StructureID.cpp
+++ b/JavaScriptCore/runtime/StructureID.cpp
@@ -30,7 +30,7 @@
 #include "PropertyNameArray.h"
 #include "StructureIDChain.h"
 #include "identifier.h"
-#include "lookup.h"
+#include "Lookup.h"
 #include <wtf/RefCountedLeakCounter.h>
 #include <wtf/RefPtr.h>
 
diff --git a/JavaScriptCore/runtime/StructureID.h b/JavaScriptCore/runtime/StructureID.h
index 4f45dac..fcd2eee 100644
--- a/JavaScriptCore/runtime/StructureID.h
+++ b/JavaScriptCore/runtime/StructureID.h
@@ -33,7 +33,7 @@
 #include "StructureIDTransitionTable.h"
 #include "TypeInfo.h"
 #include "identifier.h"
-#include "ustring.h"
+#include "UString.h"
 #include <wtf/HashFunctions.h>
 #include <wtf/HashTraits.h>
 #include <wtf/OwnArrayPtr.h>
diff --git a/JavaScriptCore/runtime/StructureIDTransitionTable.h b/JavaScriptCore/runtime/StructureIDTransitionTable.h
index dd65971..1e757d8 100644
--- a/JavaScriptCore/runtime/StructureIDTransitionTable.h
+++ b/JavaScriptCore/runtime/StructureIDTransitionTable.h
@@ -26,7 +26,7 @@
 #ifndef StructureIDTransitionTable_h
 #define StructureIDTransitionTable_h
 
-#include "ustring.h"
+#include "UString.h"
 #include <wtf/HashFunctions.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashTraits.h>
diff --git a/JavaScriptCore/runtime/SymbolTable.h b/JavaScriptCore/runtime/SymbolTable.h
index d730d58..c00f95a 100644
--- a/JavaScriptCore/runtime/SymbolTable.h
+++ b/JavaScriptCore/runtime/SymbolTable.h
@@ -30,7 +30,7 @@
 #define SymbolTable_h
 
 #include "JSObject.h"
-#include "ustring.h"
+#include "UString.h"
 #include <wtf/AlwaysInline.h>
 
 namespace JSC {
diff --git a/JavaScriptCore/runtime/TypeInfo.h b/JavaScriptCore/runtime/TypeInfo.h
new file mode 100644
index 0000000..4f0b16c
--- /dev/null
+++ b/JavaScriptCore/runtime/TypeInfo.h
@@ -0,0 +1,63 @@
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * 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 TypeInfo_h
+#define TypeInfo_h
+
+#include "JSType.h"
+
+namespace JSC {
+
+    // WebCore uses MasqueradesAsUndefined to make document.all and style.filter undetectable.
+    static const unsigned MasqueradesAsUndefined = 1;
+    static const unsigned ImplementsHasInstance = 1 << 1;
+    static const unsigned OverridesHasInstance = 1 << 2;
+    static const unsigned NeedsThisConversion = 1 << 3;
+    static const unsigned HasStandardGetOwnPropertySlot = 1 << 4;
+
+    class TypeInfo {
+        friend class CTI;
+    public:
+        TypeInfo(JSType type, unsigned flags = 0) : m_type(type), m_flags(flags) { }
+
+        JSType type() const { return m_type; }
+
+        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 hasStandardGetOwnPropertySlot() const { return m_flags & HasStandardGetOwnPropertySlot; }
+
+        unsigned flags() const { return m_flags; }
+
+    private:
+        JSType m_type;
+        unsigned m_flags;
+    };
+
+}
+
+#endif // TypeInfo_h
diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp
new file mode 100644
index 0000000..395933f
--- /dev/null
+++ b/JavaScriptCore/runtime/UString.cpp
@@ -0,0 +1,1638 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ *
+ *  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 "UString.h"
+
+#include "JSGlobalObjectFunctions.h"
+#include "Collector.h"
+#include "dtoa.h"
+#include "identifier.h"
+#include "Operations.h"
+#include <ctype.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/UTF8.h>
+
+#if HAVE(STRING_H)
+#include <string.h>
+#endif
+#if HAVE(STRINGS_H)
+#include <strings.h>
+#endif
+
+using namespace WTF;
+using namespace WTF::Unicode;
+using namespace std;
+
+// This can be tuned differently per platform by putting platform #ifs right here.
+// If you don't define this macro at all, then copyChars will just call directly
+// to memcpy.
+#define USTRING_COPY_CHARS_INLINE_CUTOFF 20
+
+namespace JSC {
+ 
+extern const double NaN;
+extern const double Inf;
+
+static inline size_t overflowIndicator() { return std::numeric_limits<size_t>::max(); }
+static inline size_t maxUChars() { return std::numeric_limits<size_t>::max() / sizeof(UChar); }
+
+static inline UChar* allocChars(size_t length)
+{
+    ASSERT(length);
+    if (length > maxUChars())
+        return 0;
+    return static_cast<UChar*>(tryFastMalloc(sizeof(UChar) * length));
+}
+
+static inline UChar* reallocChars(UChar* buffer, size_t length)
+{
+    ASSERT(length);
+    if (length > maxUChars())
+        return 0;
+    return static_cast<UChar*>(tryFastRealloc(buffer, sizeof(UChar) * length));
+}
+
+static inline void copyChars(UChar* destination, const UChar* source, unsigned numCharacters)
+{
+#ifdef USTRING_COPY_CHARS_INLINE_CUTOFF
+    if (numCharacters <= USTRING_COPY_CHARS_INLINE_CUTOFF) {
+        for (unsigned i = 0; i < numCharacters; ++i)
+            destination[i] = source[i];
+        return;
+    }
+#endif
+    memcpy(destination, source, numCharacters * sizeof(UChar));
+}
+
+COMPILE_ASSERT(sizeof(UChar) == 2, uchar_is_2_bytes)
+
+CString::CString(const char* c)
+    : m_length(strlen(c))
+    , m_data(new char[m_length + 1])
+{
+    memcpy(m_data, c, m_length + 1);
+}
+
+CString::CString(const char* c, size_t length)
+    : m_length(length)
+    , m_data(new char[length + 1])
+{
+    memcpy(m_data, c, m_length);
+    m_data[m_length] = 0;
+}
+
+CString::CString(const CString& b)
+{
+    m_length = b.m_length;
+    if (b.m_data) {
+        m_data = new char[m_length + 1];
+        memcpy(m_data, b.m_data, m_length + 1);
+    } else
+        m_data = 0;
+}
+
+CString::~CString()
+{
+    delete [] m_data;
+}
+
+CString CString::adopt(char* c, size_t length)
+{
+    CString s;
+    s.m_data = c;
+    s.m_length = length;
+    return s;
+}
+
+CString& CString::append(const CString& t)
+{
+    char* n;
+    n = new char[m_length + t.m_length + 1];
+    if (m_length)
+        memcpy(n, m_data, m_length);
+    if (t.m_length)
+        memcpy(n + m_length, t.m_data, t.m_length);
+    m_length += t.m_length;
+    n[m_length] = 0;
+
+    delete [] m_data;
+    m_data = n;
+
+    return *this;
+}
+
+CString& CString::operator=(const char* c)
+{
+    if (m_data)
+        delete [] m_data;
+    m_length = strlen(c);
+    m_data = new char[m_length + 1];
+    memcpy(m_data, c, m_length + 1);
+
+    return *this;
+}
+
+CString& CString::operator=(const CString& str)
+{
+    if (this == &str)
+        return *this;
+
+    if (m_data)
+        delete [] m_data;
+    m_length = str.m_length;
+    if (str.m_data) {
+        m_data = new char[m_length + 1];
+        memcpy(m_data, str.m_data, m_length + 1);
+    } else
+        m_data = 0;
+
+    return *this;
+}
+
+bool operator==(const CString& c1, const CString& c2)
+{
+    size_t len = c1.size();
+    return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0);
+}
+
+// These static strings are immutable, except for rc, whose initial value is chosen to 
+// reduce the possibility of it becoming zero due to ref/deref not being thread-safe.
+static UChar sharedEmptyChar;
+UString::Rep UString::Rep::null = { 0, 0, INT_MAX / 2, 0, 1, &UString::Rep::null, 0, 0, 0, 0, 0, 0 };
+UString::Rep UString::Rep::empty = { 0, 0, INT_MAX / 2, 0, 1, &UString::Rep::empty, 0, &sharedEmptyChar, 0, 0, 0, 0 };
+
+static char* statBuffer = 0; // Only used for debugging via UString::ascii().
+
+PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar* d, int l)
+{
+    UChar* copyD = static_cast<UChar*>(fastMalloc(l * sizeof(UChar)));
+    copyChars(copyD, d, l);
+    return create(copyD, l);
+}
+
+PassRefPtr<UString::Rep> UString::Rep::create(UChar* d, int l)
+{
+    Rep* r = new Rep;
+    r->offset = 0;
+    r->len = l;
+    r->rc = 1;
+    r->_hash = 0;
+    r->m_identifierTable = 0;
+    r->baseString = r;
+    r->reportedCost = 0;
+    r->buf = d;
+    r->usedCapacity = l;
+    r->capacity = l;
+    r->usedPreCapacity = 0;
+    r->preCapacity = 0;
+
+    r->checkConsistency();
+
+    // steal the single reference this Rep was created with
+    return adoptRef(r);
+}
+
+PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, int length)
+{
+    ASSERT(base);
+    base->checkConsistency();
+
+    int baseOffset = base->offset;
+
+    base = base->baseString;
+
+    ASSERT(-(offset + baseOffset) <= base->usedPreCapacity);
+    ASSERT(offset + baseOffset + length <= base->usedCapacity);
+
+    Rep* r = new Rep;
+    r->offset = baseOffset + offset;
+    r->len = length;
+    r->rc = 1;
+    r->_hash = 0;
+    r->m_identifierTable = 0;
+    r->baseString = base.releaseRef();
+    r->reportedCost = 0;
+    r->buf = 0;
+    r->usedCapacity = 0;
+    r->capacity = 0;
+    r->usedPreCapacity = 0;
+    r->preCapacity = 0;
+
+    r->checkConsistency();
+
+    // steal the single reference this Rep was created with
+    return adoptRef(r);
+}
+
+PassRefPtr<UString::Rep> UString::Rep::createFromUTF8(const char* string)
+{
+    if (!string)
+        return &UString::Rep::null;
+
+    size_t length = strlen(string);
+    Vector<UChar, 1024> buffer(length);
+    UChar* p = buffer.data();
+    if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length))
+        return &UString::Rep::null;
+
+    return UString::Rep::createCopying(buffer.data(), p - buffer.data());
+}
+
+void UString::Rep::destroy()
+{
+    checkConsistency();
+
+    // Static null and empty strings can never be destroyed, but we cannot rely on 
+    // reference counting, because ref/deref are not thread-safe.
+    if (!isStatic()) {
+        if (identifierTable())
+            Identifier::remove(this);
+        if (baseString == this)
+            fastFree(buf);
+        else
+            baseString->deref();
+
+        delete this;
+    }
+}
+
+// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
+// or anything like that.
+const unsigned PHI = 0x9e3779b9U;
+
+// Paul Hsieh's SuperFastHash
+// http://www.azillionmonkeys.com/qed/hash.html
+unsigned UString::Rep::computeHash(const UChar* s, int len)
+{
+    unsigned l = len;
+    uint32_t hash = PHI;
+    uint32_t tmp;
+
+    int rem = l & 1;
+    l >>= 1;
+
+    // Main loop
+    for (; l > 0; l--) {
+        hash += s[0];
+        tmp = (s[1] << 11) ^ hash;
+        hash = (hash << 16) ^ tmp;
+        s += 2;
+        hash += hash >> 11;
+    }
+
+    // Handle end case
+    if (rem) {
+        hash += s[0];
+        hash ^= hash << 11;
+        hash += hash >> 17;
+    }
+
+    // Force "avalanching" of final 127 bits
+    hash ^= hash << 3;
+    hash += hash >> 5;
+    hash ^= hash << 2;
+    hash += hash >> 15;
+    hash ^= hash << 10;
+
+    // this avoids ever returning a hash code of 0, since that is used to
+    // signal "hash not computed yet", using a value that is likely to be
+    // effectively the same as 0 when the low bits are masked
+    if (hash == 0)
+        hash = 0x80000000;
+
+    return hash;
+}
+
+// Paul Hsieh's SuperFastHash
+// http://www.azillionmonkeys.com/qed/hash.html
+unsigned UString::Rep::computeHash(const char* s, int l)
+{
+    // This hash is designed to work on 16-bit chunks at a time. But since the normal case
+    // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
+    // were 16-bit chunks, which should give matching results
+
+    uint32_t hash = PHI;
+    uint32_t tmp;
+
+    size_t rem = l & 1;
+    l >>= 1;
+
+    // Main loop
+    for (; l > 0; l--) {
+        hash += static_cast<unsigned char>(s[0]);
+        tmp = (static_cast<unsigned char>(s[1]) << 11) ^ hash;
+        hash = (hash << 16) ^ tmp;
+        s += 2;
+        hash += hash >> 11;
+    }
+
+    // Handle end case
+    if (rem) {
+        hash += static_cast<unsigned char>(s[0]);
+        hash ^= hash << 11;
+        hash += hash >> 17;
+    }
+
+    // Force "avalanching" of final 127 bits
+    hash ^= hash << 3;
+    hash += hash >> 5;
+    hash ^= hash << 2;
+    hash += hash >> 15;
+    hash ^= hash << 10;
+
+    // this avoids ever returning a hash code of 0, since that is used to
+    // signal "hash not computed yet", using a value that is likely to be
+    // effectively the same as 0 when the low bits are masked
+    if (hash == 0)
+        hash = 0x80000000;
+
+    return hash;
+}
+
+#ifndef NDEBUG
+void UString::Rep::checkConsistency() const
+{
+    // Only base strings have non-zero shared data.
+    if (this != baseString) {
+        ASSERT(!buf);
+        ASSERT(!usedCapacity);
+        ASSERT(!capacity);
+        ASSERT(!usedPreCapacity);
+        ASSERT(!preCapacity);
+    }
+
+    // There is no recursion for base strings.
+    ASSERT(baseString == baseString->baseString);
+
+    if (isStatic()) {
+        // There are only two static strings: null and empty.
+        ASSERT(!len);
+
+        // Static strings cannot get in identifier tables, because they are globally shared.
+        ASSERT(!identifierTable());
+    }
+
+    // The string fits in buffer.
+    ASSERT(baseString->usedPreCapacity <= baseString->preCapacity);
+    ASSERT(baseString->usedCapacity <= baseString->capacity);
+    ASSERT(-offset <= baseString->usedPreCapacity);
+    ASSERT(offset + len <= baseString->usedCapacity);
+}
+#endif
+
+// put these early so they can be inlined
+static inline size_t expandedSize(size_t size, size_t otherSize)
+{
+    // Do the size calculation in two parts, returning overflowIndicator if
+    // we overflow the maximum value that we can handle.
+
+    if (size > maxUChars())
+        return overflowIndicator();
+
+    size_t expandedSize = ((size + 10) / 10 * 11) + 1;
+    if (maxUChars() - expandedSize < otherSize)
+        return overflowIndicator();
+
+    return expandedSize + otherSize;
+}
+
+inline int UString::usedCapacity() const
+{
+    return m_rep->baseString->usedCapacity;
+}
+
+inline int UString::usedPreCapacity() const
+{
+    return m_rep->baseString->usedPreCapacity;
+}
+
+
+static inline bool expandCapacity(UString::Rep* rep, int requiredLength)
+{
+    rep->checkConsistency();
+
+    UString::Rep* r = rep->baseString;
+
+    if (requiredLength > r->capacity) {
+        size_t newCapacity = expandedSize(requiredLength, r->preCapacity);
+        UChar* oldBuf = r->buf;
+        r->buf = reallocChars(r->buf, newCapacity);
+        if (!r->buf) {
+            r->buf = oldBuf;
+            return false;
+        }
+        r->capacity = newCapacity - r->preCapacity;
+    }
+    if (requiredLength > r->usedCapacity)
+        r->usedCapacity = requiredLength;
+
+    rep->checkConsistency();
+    return true;
+}
+
+void UString::expandCapacity(int requiredLength)
+{
+    if (!JSC::expandCapacity(m_rep.get(), requiredLength))
+        makeNull();
+}
+
+void UString::expandPreCapacity(int requiredPreCap)
+{
+    m_rep->checkConsistency();
+
+    Rep* r = m_rep->baseString;
+
+    if (requiredPreCap > r->preCapacity) {
+        size_t newCapacity = expandedSize(requiredPreCap, r->capacity);
+        int delta = newCapacity - r->capacity - r->preCapacity;
+
+        UChar* newBuf = allocChars(newCapacity);
+        if (!newBuf) {
+            makeNull();
+            return;
+        }
+        copyChars(newBuf + delta, r->buf, r->capacity + r->preCapacity);
+        fastFree(r->buf);
+        r->buf = newBuf;
+
+        r->preCapacity = newCapacity - r->capacity;
+    }
+    if (requiredPreCap > r->usedPreCapacity)
+        r->usedPreCapacity = requiredPreCap;
+
+    m_rep->checkConsistency();
+}
+
+PassRefPtr<UString::Rep> createRep(const char* c)
+{
+    if (!c)
+        return &UString::Rep::null;
+
+    if (!c[0])
+        return &UString::Rep::empty;
+
+    size_t length = strlen(c);
+    UChar* d = allocChars(length);
+    if (!d)
+        return &UString::Rep::null;
+    else {
+        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
+        return UString::Rep::create(d, static_cast<int>(length));
+    }
+
+}
+
+UString::UString(const char* c)
+    : m_rep(createRep(c))
+{
+}
+
+UString::UString(const UChar* c, int length)
+{
+    if (length == 0) 
+        m_rep = &Rep::empty;
+    else
+        m_rep = Rep::createCopying(c, length);
+}
+
+UString::UString(UChar* c, int length, bool copy)
+{
+    if (length == 0)
+        m_rep = &Rep::empty;
+    else if (copy)
+        m_rep = Rep::createCopying(c, length);
+    else
+        m_rep = Rep::create(c, length);
+}
+
+UString::UString(const Vector<UChar>& buffer)
+{
+    if (!buffer.size())
+        m_rep = &Rep::empty;
+    else
+        m_rep = Rep::createCopying(buffer.data(), buffer.size());
+}
+
+static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Rep> r, const UChar* tData, int tSize)
+{
+    RefPtr<UString::Rep> rep = r;
+
+    rep->checkConsistency();
+
+    int thisSize = rep->size();
+    int thisOffset = rep->offset;
+    int length = thisSize + tSize;
+
+    // possible cases:
+    if (tSize == 0) {
+        // t is empty
+    } else if (thisSize == 0) {
+        // this is empty
+        rep = UString::Rep::createCopying(tData, tSize);
+    } else if (rep->baseIsSelf() && rep->rc == 1) {
+        // this is direct and has refcount of 1 (so we can just alter it directly)
+        if (!expandCapacity(rep.get(), thisOffset + length))
+            rep = &UString::Rep::null;
+        if (rep->data()) {
+            copyChars(rep->data() + thisSize, tData, tSize);
+            rep->len = length;
+            rep->_hash = 0;
+        }
+    } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) {
+        // this reaches the end of the buffer - extend it if it's long enough to append to
+        if (!expandCapacity(rep.get(), thisOffset + length))
+            rep = &UString::Rep::null;
+        if (rep->data()) {
+            copyChars(rep->data() + thisSize, tData, tSize);
+            rep = UString::Rep::create(rep, 0, length);
+        }
+    } else {
+        // this is shared with someone using more capacity, gotta make a whole new string
+        size_t newCapacity = expandedSize(length, 0);
+        UChar* d = allocChars(newCapacity);
+        if (!d)
+            rep = &UString::Rep::null;
+        else {
+            copyChars(d, rep->data(), thisSize);
+            copyChars(d + thisSize, tData, tSize);
+            rep = UString::Rep::create(d, length);
+            rep->capacity = newCapacity;
+        }
+    }
+
+    rep->checkConsistency();
+
+    return rep.release();
+}
+
+static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Rep> r, const char* t)
+{
+    RefPtr<UString::Rep> rep = r;
+
+    rep->checkConsistency();
+
+    int thisSize = rep->size();
+    int thisOffset = rep->offset;
+    int tSize = static_cast<int>(strlen(t));
+    int length = thisSize + tSize;
+
+    // possible cases:
+    if (thisSize == 0) {
+        // this is empty
+        rep = createRep(t);
+    } else if (tSize == 0) {
+        // t is empty, we'll just return *this below.
+    } else if (rep->baseIsSelf() && rep->rc == 1) {
+        // this is direct and has refcount of 1 (so we can just alter it directly)
+        expandCapacity(rep.get(), thisOffset + length);
+        UChar* d = rep->data();
+        if (d) {
+            for (int i = 0; i < tSize; ++i)
+                d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
+            rep->len = length;
+            rep->_hash = 0;
+        }
+    } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) {
+        // this string reaches the end of the buffer - extend it
+        expandCapacity(rep.get(), thisOffset + length);
+        UChar* d = rep->data();
+        if (d) {
+            for (int i = 0; i < tSize; ++i)
+                d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
+            rep = UString::Rep::create(rep, 0, length);
+        }
+    } else {
+        // this is shared with someone using more capacity, gotta make a whole new string
+        size_t newCapacity = expandedSize(length, 0);
+        UChar* d = allocChars(newCapacity);
+        if (!d)
+            rep = &UString::Rep::null;
+        else {
+            copyChars(d, rep->data(), thisSize);
+            for (int i = 0; i < tSize; ++i)
+                d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
+            rep = UString::Rep::create(d, length);
+            rep->capacity = newCapacity;
+        }
+    }
+
+    rep->checkConsistency();
+
+    return rep.release();
+}
+
+PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b)
+{
+    a->checkConsistency();
+    b->checkConsistency();
+
+    int aSize = a->size();
+    int aOffset = a->offset;
+    int bSize = b->size();
+    int bOffset = b->offset;
+    int length = aSize + bSize;
+
+    // possible cases:
+
+    // a is empty
+    if (aSize == 0)
+        return b;
+    // b is empty
+    if (bSize == 0)
+        return a;
+
+    if (bSize == 1 && aOffset + aSize == a->baseString->usedCapacity && aOffset + length <= a->baseString->capacity) {
+        // b is a single character (common fast case)
+        a->baseString->usedCapacity = aOffset + length;
+        a->data()[aSize] = b->data()[0];
+        return UString::Rep::create(a, 0, length);
+    }
+
+    if (aOffset + aSize == a->baseString->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize &&
+               (-bOffset != b->baseString->usedPreCapacity || aSize >= bSize)) {
+        // - a reaches the end of its buffer so it qualifies for shared append
+        // - also, it's at least a quarter the length of b - appending to a much shorter
+        //   string does more harm than good
+        // - however, if b qualifies for prepend and is longer than a, we'd rather prepend
+        UString x(a);
+        x.expandCapacity(aOffset + length);
+        if (!a->data() || !x.data())
+            return 0;
+        copyChars(a->data() + aSize, b->data(), bSize);
+        PassRefPtr<UString::Rep> result = UString::Rep::create(a, 0, length);
+
+        a->checkConsistency();
+        b->checkConsistency();
+        result->checkConsistency();
+
+        return result;
+    }
+
+    if (-bOffset == b->baseString->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) {
+        // - b reaches the beginning of its buffer so it qualifies for shared prepend
+        // - also, it's at least a quarter the length of a - prepending to a much shorter
+        //   string does more harm than good
+        UString y(b);
+        y.expandPreCapacity(-bOffset + aSize);
+        if (!b->data() || !y.data())
+            return 0;
+        copyChars(b->data() - aSize, a->data(), aSize);
+        PassRefPtr<UString::Rep> result = UString::Rep::create(b, -aSize, length);
+
+        a->checkConsistency();
+        b->checkConsistency();
+        result->checkConsistency();
+
+        return result;
+    }
+
+    // a does not qualify for append, and b does not qualify for prepend, gotta make a whole new string
+    size_t newCapacity = expandedSize(length, 0);
+    UChar* d = allocChars(newCapacity);
+    if (!d)
+        return 0;
+    copyChars(d, a->data(), aSize);
+    copyChars(d + aSize, b->data(), bSize);
+    PassRefPtr<UString::Rep> result = UString::Rep::create(d, length);
+    result->capacity = newCapacity;
+
+    a->checkConsistency();
+    b->checkConsistency();
+    result->checkConsistency();
+
+    return result;
+}
+
+PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, int i)
+{
+    UChar buf[1 + sizeof(i) * 3];
+    UChar* end = buf + sizeof(buf) / sizeof(UChar);
+    UChar* p = end;
+  
+    if (i == 0)
+        *--p = '0';
+    else if (i == INT_MIN) {
+        char minBuf[1 + sizeof(i) * 3];
+        sprintf(minBuf, "%d", INT_MIN);
+        return concatenate(rep, minBuf);
+    } else {
+        bool negative = false;
+        if (i < 0) {
+            negative = true;
+            i = -i;
+        }
+        while (i) {
+            *--p = static_cast<unsigned short>((i % 10) + '0');
+            i /= 10;
+        }
+        if (negative)
+            *--p = '-';
+    }
+
+    return concatenate(rep, p, static_cast<int>(end - p));
+
+}
+
+PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, double d)
+{
+    // avoid ever printing -NaN, in JS conceptually there is only one NaN value
+    if (isnan(d))
+        return concatenate(rep, "NaN");
+
+    if (d == 0.0) // stringify -0 as 0
+        d = 0.0;
+
+    char buf[80];
+    int decimalPoint;
+    int sign;
+
+    char* result = dtoa(d, 0, &decimalPoint, &sign, NULL);
+    int length = static_cast<int>(strlen(result));
+  
+    int i = 0;
+    if (sign)
+        buf[i++] = '-';
+  
+    if (decimalPoint <= 0 && decimalPoint > -6) {
+        buf[i++] = '0';
+        buf[i++] = '.';
+        for (int j = decimalPoint; j < 0; j++)
+            buf[i++] = '0';
+        strcpy(buf + i, result);
+    } else if (decimalPoint <= 21 && decimalPoint > 0) {
+        if (length <= decimalPoint) {
+            strcpy(buf + i, result);
+            i += length;
+            for (int j = 0; j < decimalPoint - length; j++)
+                buf[i++] = '0';
+            buf[i] = '\0';
+        } else {
+            strncpy(buf + i, result, decimalPoint);
+            i += decimalPoint;
+            buf[i++] = '.';
+            strcpy(buf + i, result + decimalPoint);
+        }
+    } else if (result[0] < '0' || result[0] > '9')
+        strcpy(buf + i, result);
+    else {
+        buf[i++] = result[0];
+        if (length > 1) {
+            buf[i++] = '.';
+            strcpy(buf + i, result + 1);
+            i += length - 1;
+        }
+        
+        buf[i++] = 'e';
+        buf[i++] = (decimalPoint >= 0) ? '+' : '-';
+        // decimalPoint can't be more than 3 digits decimal given the
+        // nature of float representation
+        int exponential = decimalPoint - 1;
+        if (exponential < 0)
+            exponential = -exponential;
+        if (exponential >= 100)
+            buf[i++] = static_cast<char>('0' + exponential / 100);
+        if (exponential >= 10)
+            buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
+        buf[i++] = static_cast<char>('0' + exponential % 10);
+        buf[i++] = '\0';
+    }
+    
+  freedtoa(result);
+
+  return concatenate(rep, buf);
+}
+
+const UString& UString::null()
+{
+    static UString* n = new UString; // Should be called from main thread at least once to be safely initialized.
+    return *n;
+}
+
+UString UString::from(int i)
+{
+    UChar buf[1 + sizeof(i) * 3];
+    UChar* end = buf + sizeof(buf) / sizeof(UChar);
+    UChar* p = end;
+  
+    if (i == 0)
+        *--p = '0';
+    else if (i == INT_MIN) {
+        char minBuf[1 + sizeof(i) * 3];
+        sprintf(minBuf, "%d", INT_MIN);
+        return UString(minBuf);
+    } else {
+        bool negative = false;
+        if (i < 0) {
+            negative = true;
+            i = -i;
+        }
+        while (i) {
+            *--p = static_cast<unsigned short>((i % 10) + '0');
+            i /= 10;
+        }
+        if (negative)
+            *--p = '-';
+    }
+
+    return UString(p, static_cast<int>(end - p));
+}
+
+UString UString::from(unsigned int u)
+{
+    UChar buf[sizeof(u) * 3];
+    UChar* end = buf + sizeof(buf) / sizeof(UChar);
+    UChar* p = end;
+    
+    if (u == 0)
+        *--p = '0';
+    else {
+        while (u) {
+            *--p = static_cast<unsigned short>((u % 10) + '0');
+            u /= 10;
+        }
+    }
+    
+    return UString(p, static_cast<int>(end - p));
+}
+
+UString UString::from(long l)
+{
+    UChar buf[1 + sizeof(l) * 3];
+    UChar* end = buf + sizeof(buf) / sizeof(UChar);
+    UChar* p = end;
+
+    if (l == 0)
+        *--p = '0';
+    else if (l == LONG_MIN) {
+        char minBuf[1 + sizeof(l) * 3];
+        sprintf(minBuf, "%ld", LONG_MIN);
+        return UString(minBuf);
+    } else {
+        bool negative = false;
+        if (l < 0) {
+            negative = true;
+            l = -l;
+        }
+        while (l) {
+            *--p = static_cast<unsigned short>((l % 10) + '0');
+            l /= 10;
+        }
+        if (negative)
+            *--p = '-';
+    }
+
+    return UString(p, static_cast<int>(end - p));
+}
+
+UString UString::from(double d)
+{
+    // avoid ever printing -NaN, in JS conceptually there is only one NaN value
+    if (isnan(d))
+        return "NaN";
+
+    char buf[80];
+    int decimalPoint;
+    int sign;
+
+    char* result = dtoa(d, 0, &decimalPoint, &sign, NULL);
+    int length = static_cast<int>(strlen(result));
+  
+    int i = 0;
+    if (sign)
+        buf[i++] = '-';
+  
+    if (decimalPoint <= 0 && decimalPoint > -6) {
+        buf[i++] = '0';
+        buf[i++] = '.';
+        for (int j = decimalPoint; j < 0; j++)
+            buf[i++] = '0';
+        strcpy(buf + i, result);
+    } else if (decimalPoint <= 21 && decimalPoint > 0) {
+        if (length <= decimalPoint) {
+            strcpy(buf + i, result);
+            i += length;
+            for (int j = 0; j < decimalPoint - length; j++)
+                buf[i++] = '0';
+            buf[i] = '\0';
+        } else {
+            strncpy(buf + i, result, decimalPoint);
+            i += decimalPoint;
+            buf[i++] = '.';
+            strcpy(buf + i, result + decimalPoint);
+        }
+    } else if (result[0] < '0' || result[0] > '9')
+        strcpy(buf + i, result);
+    else {
+        buf[i++] = result[0];
+        if (length > 1) {
+            buf[i++] = '.';
+            strcpy(buf + i, result + 1);
+            i += length - 1;
+        }
+        
+        buf[i++] = 'e';
+        buf[i++] = (decimalPoint >= 0) ? '+' : '-';
+        // decimalPoint can't be more than 3 digits decimal given the
+        // nature of float representation
+        int exponential = decimalPoint - 1;
+        if (exponential < 0)
+            exponential = -exponential;
+        if (exponential >= 100)
+            buf[i++] = static_cast<char>('0' + exponential / 100);
+        if (exponential >= 10)
+            buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
+        buf[i++] = static_cast<char>('0' + exponential % 10);
+        buf[i++] = '\0';
+    }
+    
+  freedtoa(result);
+
+  return UString(buf);
+}
+
+UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
+{
+    m_rep->checkConsistency();
+
+    if (rangeCount == 1 && separatorCount == 0) {
+        int thisSize = size();
+        int position = substringRanges[0].position;
+        int length = substringRanges[0].length;
+        if (position <= 0 && length >= thisSize)
+            return *this;
+        return UString::Rep::create(m_rep, max(0, position), min(thisSize, length));
+    }
+
+    int totalLength = 0;
+    for (int i = 0; i < rangeCount; i++)
+        totalLength += substringRanges[i].length;
+    for (int i = 0; i < separatorCount; i++)
+        totalLength += separators[i].size();
+
+    if (totalLength == 0)
+        return "";
+
+    UChar* buffer = allocChars(totalLength);
+    if (!buffer)
+        return null();
+
+    int maxCount = max(rangeCount, separatorCount);
+    int bufferPos = 0;
+    for (int i = 0; i < maxCount; i++) {
+        if (i < rangeCount) {
+            copyChars(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length);
+            bufferPos += substringRanges[i].length;
+        }
+        if (i < separatorCount) {
+            copyChars(buffer + bufferPos, separators[i].data(), separators[i].size());
+            bufferPos += separators[i].size();
+        }
+    }
+
+    return UString::Rep::create(buffer, totalLength);
+}
+
+UString& UString::append(const UString &t)
+{
+    m_rep->checkConsistency();
+    t.rep()->checkConsistency();
+
+    int thisSize = size();
+    int thisOffset = m_rep->offset;
+    int tSize = t.size();
+    int length = thisSize + tSize;
+
+    // possible cases:
+    if (thisSize == 0) {
+        // this is empty
+        *this = t;
+    } else if (tSize == 0) {
+        // t is empty
+    } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
+        // this is direct and has refcount of 1 (so we can just alter it directly)
+        expandCapacity(thisOffset + length);
+        if (data()) {
+            copyChars(m_rep->data() + thisSize, t.data(), tSize);
+            m_rep->len = length;
+            m_rep->_hash = 0;
+        }
+    } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
+        // this reaches the end of the buffer - extend it if it's long enough to append to
+        expandCapacity(thisOffset + length);
+        if (data()) {
+            copyChars(m_rep->data() + thisSize, t.data(), tSize);
+            m_rep = Rep::create(m_rep, 0, length);
+        }
+    } else {
+        // this is shared with someone using more capacity, gotta make a whole new string
+        size_t newCapacity = expandedSize(length, 0);
+        UChar* d = allocChars(newCapacity);
+        if (!d)
+            makeNull();
+        else {
+            copyChars(d, data(), thisSize);
+            copyChars(d + thisSize, t.data(), tSize);
+            m_rep = Rep::create(d, length);
+            m_rep->capacity = newCapacity;
+        }
+    }
+
+    m_rep->checkConsistency();
+    t.rep()->checkConsistency();
+
+    return *this;
+}
+
+UString& UString::append(const UChar* tData, int tSize)
+{
+    m_rep = concatenate(m_rep.release(), tData, tSize);
+    return *this;
+}
+
+UString& UString::append(const char* t)
+{
+    m_rep = concatenate(m_rep.release(), t);
+    return *this;
+}
+
+UString& UString::append(UChar c)
+{
+    m_rep->checkConsistency();
+
+    int thisOffset = m_rep->offset;
+    int length = size();
+
+    // possible cases:
+    if (length == 0) {
+        // this is empty - must make a new m_rep because we don't want to pollute the shared empty one 
+        size_t newCapacity = expandedSize(1, 0);
+        UChar* d = allocChars(newCapacity);
+        if (!d)
+            makeNull();
+        else {
+            d[0] = c;
+            m_rep = Rep::create(d, 1);
+            m_rep->capacity = newCapacity;
+        }
+    } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
+        // this is direct and has refcount of 1 (so we can just alter it directly)
+        expandCapacity(thisOffset + length + 1);
+        UChar* d = m_rep->data();
+        if (d) {
+            d[length] = c;
+            m_rep->len = length + 1;
+            m_rep->_hash = 0;
+        }
+    } else if (thisOffset + length == usedCapacity() && length >= minShareSize) {
+        // this reaches the end of the string - extend it and share
+        expandCapacity(thisOffset + length + 1);
+        UChar* d = m_rep->data();
+        if (d) {
+            d[length] = c;
+            m_rep = Rep::create(m_rep, 0, length + 1);
+        }
+    } else {
+        // this is shared with someone using more capacity, gotta make a whole new string
+        size_t newCapacity = expandedSize(length + 1, 0);
+        UChar* d = allocChars(newCapacity);
+        if (!d)
+            makeNull();
+        else {
+            copyChars(d, data(), length);
+            d[length] = c;
+            m_rep = Rep::create(d, length + 1);
+            m_rep->capacity = newCapacity;
+        }
+    }
+
+    m_rep->checkConsistency();
+
+    return *this;
+}
+
+bool UString::getCString(CStringBuffer& buffer) const
+{
+    int length = size();
+    int neededSize = length + 1;
+    buffer.resize(neededSize);
+    char* buf = buffer.data();
+
+    UChar ored = 0;
+    const UChar* p = data();
+    char* q = buf;
+    const UChar* limit = p + length;
+    while (p != limit) {
+        UChar c = p[0];
+        ored |= c;
+        *q = static_cast<char>(c);
+        ++p;
+        ++q;
+    }
+    *q = '\0';
+
+    return !(ored & 0xFF00);
+}
+
+char* UString::ascii() const
+{
+    int length = size();
+    int neededSize = length + 1;
+    delete[] statBuffer;
+    statBuffer = new char[neededSize];
+
+    const UChar* p = data();
+    char* q = statBuffer;
+    const UChar* limit = p + length;
+    while (p != limit) {
+        *q = static_cast<char>(p[0]);
+        ++p;
+        ++q;
+    }
+    *q = '\0';
+
+    return statBuffer;
+}
+
+UString& UString::operator=(const char* c)
+{
+    if (!c) {
+        m_rep = &Rep::null;
+        return *this;
+    }
+
+    if (!c[0]) {
+        m_rep = &Rep::empty;
+        return *this;
+    }
+
+    int l = static_cast<int>(strlen(c));
+    UChar* d;
+    if (m_rep->rc == 1 && l <= m_rep->capacity && m_rep->baseIsSelf() && m_rep->offset == 0 && m_rep->preCapacity == 0) {
+        d = m_rep->buf;
+        m_rep->_hash = 0;
+        m_rep->len = l;
+    } else {
+        d = allocChars(l);
+        if (!d) {
+            makeNull();
+            return *this;
+        }
+        m_rep = Rep::create(d, l);
+    }
+    for (int i = 0; i < l; i++)
+        d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
+
+    return *this;
+}
+
+bool UString::is8Bit() const
+{
+    const UChar* u = data();
+    const UChar* limit = u + size();
+    while (u < limit) {
+        if (u[0] > 0xFF)
+            return false;
+        ++u;
+    }
+
+    return true;
+}
+
+UChar UString::operator[](int pos) const
+{
+    if (pos >= size())
+        return '\0';
+    return data()[pos];
+}
+
+double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
+{
+    if (size() == 1) {
+        UChar c = data()[0];
+        if (isASCIIDigit(c))
+            return c - '0';
+        if (isASCIISpace(c) && tolerateEmptyString)
+            return 0;
+        return NaN;
+    }
+
+    // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk
+    // after the number, so this is too strict a check.
+    CStringBuffer s;
+    if (!getCString(s))
+        return NaN;
+    const char* c = s.data();
+
+    // skip leading white space
+    while (isASCIISpace(*c))
+        c++;
+
+    // empty string ?
+    if (*c == '\0')
+        return tolerateEmptyString ? 0.0 : NaN;
+
+    double d;
+
+    // hex number ?
+    if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
+        const char* firstDigitPosition = c + 2;
+        c++;
+        d = 0.0;
+        while (*(++c)) {
+            if (*c >= '0' && *c <= '9')
+                d = d * 16.0 + *c - '0';
+            else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
+                d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
+            else
+                break;
+        }
+
+        if (d >= mantissaOverflowLowerBound)
+            d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
+    } else {
+        // regular number ?
+        char* end;
+        d = strtod(c, &end);
+        if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
+            c = end;
+        } else {
+            double sign = 1.0;
+
+            if (*c == '+')
+                c++;
+            else if (*c == '-') {
+                sign = -1.0;
+                c++;
+            }
+
+            // We used strtod() to do the conversion. However, strtod() handles
+            // infinite values slightly differently than JavaScript in that it
+            // converts the string "inf" with any capitalization to infinity,
+            // whereas the ECMA spec requires that it be converted to NaN.
+
+            if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') {
+                d = sign * Inf;
+                c += 8;
+            } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
+                c = end;
+            else
+                return NaN;
+        }
+    }
+
+    // allow trailing white space
+    while (isASCIISpace(*c))
+        c++;
+    // don't allow anything after - unless tolerant=true
+    if (!tolerateTrailingJunk && *c != '\0')
+        d = NaN;
+
+    return d;
+}
+
+double UString::toDouble(bool tolerateTrailingJunk) const
+{
+    return toDouble(tolerateTrailingJunk, true);
+}
+
+double UString::toDouble() const
+{
+    return toDouble(false, true);
+}
+
+uint32_t UString::toUInt32(bool* ok) const
+{
+    double d = toDouble();
+    bool b = true;
+
+    if (d != static_cast<uint32_t>(d)) {
+        b = false;
+        d = 0;
+    }
+
+    if (ok)
+        *ok = b;
+
+    return static_cast<uint32_t>(d);
+}
+
+uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const
+{
+    double d = toDouble(false, tolerateEmptyString);
+    bool b = true;
+
+    if (d != static_cast<uint32_t>(d)) {
+        b = false;
+        d = 0;
+    }
+
+    if (ok)
+        *ok = b;
+
+    return static_cast<uint32_t>(d);
+}
+
+uint32_t UString::toStrictUInt32(bool* ok) const
+{
+    if (ok)
+        *ok = false;
+
+    // Empty string is not OK.
+    int len = m_rep->len;
+    if (len == 0)
+        return 0;
+    const UChar* p = m_rep->data();
+    unsigned short c = p[0];
+
+    // If the first digit is 0, only 0 itself is OK.
+    if (c == '0') {
+        if (len == 1 && ok)
+            *ok = true;
+        return 0;
+    }
+
+    // Convert to UInt32, checking for overflow.
+    uint32_t i = 0;
+    while (1) {
+        // Process character, turning it into a digit.
+        if (c < '0' || c > '9')
+            return 0;
+        const unsigned d = c - '0';
+
+        // Multiply by 10, checking for overflow out of 32 bits.
+        if (i > 0xFFFFFFFFU / 10)
+            return 0;
+        i *= 10;
+
+        // Add in the digit, checking for overflow out of 32 bits.
+        const unsigned max = 0xFFFFFFFFU - d;
+        if (i > max)
+            return 0;
+        i += d;
+
+        // Handle end of string.
+        if (--len == 0) {
+            if (ok)
+                *ok = true;
+            return i;
+        }
+
+        // Get next character.
+        c = *(++p);
+    }
+}
+
+int UString::find(const UString& f, int pos) const
+{
+    int sz = size();
+    int fsz = f.size();
+    if (sz < fsz)
+        return -1;
+    if (pos < 0)
+        pos = 0;
+    if (fsz == 0)
+        return pos;
+    const UChar* end = data() + sz - fsz;
+    int fsizeminusone = (fsz - 1) * sizeof(UChar);
+    const UChar* fdata = f.data();
+    unsigned short fchar = fdata[0];
+    ++fdata;
+    for (const UChar* c = data() + pos; c <= end; c++) {
+        if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone))
+            return static_cast<int>(c - data());
+    }
+
+    return -1;
+}
+
+int UString::find(UChar ch, int pos) const
+{
+    if (pos < 0)
+        pos = 0;
+    const UChar* end = data() + size();
+    for (const UChar* c = data() + pos; c < end; c++) {
+        if (*c == ch)
+            return static_cast<int>(c - data());
+    }
+    
+    return -1;
+}
+
+int UString::rfind(const UString& f, int pos) const
+{
+    int sz = size();
+    int fsz = f.size();
+    if (sz < fsz)
+        return -1;
+    if (pos < 0)
+        pos = 0;
+    if (pos > sz - fsz)
+        pos = sz - fsz;
+    if (fsz == 0)
+        return pos;
+    int fsizeminusone = (fsz - 1) * sizeof(UChar);
+    const UChar* fdata = f.data();
+    for (const UChar* c = data() + pos; c >= data(); c--) {
+        if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
+            return static_cast<int>(c - data());
+    }
+
+    return -1;
+}
+
+int UString::rfind(UChar ch, int pos) const
+{
+    if (isEmpty())
+        return -1;
+    if (pos + 1 >= size())
+        pos = size() - 1;
+    for (const UChar* c = data() + pos; c >= data(); c--) {
+        if (*c == ch)
+            return static_cast<int>(c - data());
+    }
+
+    return -1;
+}
+
+UString UString::substr(int pos, int len) const
+{
+    int s = size();
+
+    if (pos < 0)
+        pos = 0;
+    else if (pos >= s)
+        pos = s;
+    if (len < 0)
+        len = s;
+    if (pos + len >= s)
+        len = s - pos;
+
+    if (pos == 0 && len == s)
+        return *this;
+
+    return UString(Rep::create(m_rep, pos, len));
+}
+
+bool operator==(const UString& s1, const UString& s2)
+{
+    int size = s1.size();
+    switch (size) {
+        case 0:
+            return !s2.size();
+        case 1:
+            return s2.size() == 1 && s1.data()[0] == s2.data()[0];
+        default:
+            return s2.size() == size && memcmp(s1.data(), s2.data(), size * sizeof(UChar)) == 0;
+    }
+}
+
+bool operator==(const UString& s1, const char *s2)
+{
+    if (s2 == 0)
+        return s1.isEmpty();
+
+    const UChar* u = s1.data();
+    const UChar* uend = u + s1.size();
+    while (u != uend && *s2) {
+        if (u[0] != (unsigned char)*s2)
+            return false;
+        s2++;
+        u++;
+    }
+
+    return u == uend && *s2 == 0;
+}
+
+bool operator<(const UString& s1, const UString& s2)
+{
+    const int l1 = s1.size();
+    const int l2 = s2.size();
+    const int lmin = l1 < l2 ? l1 : l2;
+    const UChar* c1 = s1.data();
+    const UChar* c2 = s2.data();
+    int l = 0;
+    while (l < lmin && *c1 == *c2) {
+        c1++;
+        c2++;
+        l++;
+    }
+    if (l < lmin)
+        return (c1[0] < c2[0]);
+
+    return (l1 < l2);
+}
+
+bool operator>(const UString& s1, const UString& s2)
+{
+    const int l1 = s1.size();
+    const int l2 = s2.size();
+    const int lmin = l1 < l2 ? l1 : l2;
+    const UChar* c1 = s1.data();
+    const UChar* c2 = s2.data();
+    int l = 0;
+    while (l < lmin && *c1 == *c2) {
+        c1++;
+        c2++;
+        l++;
+    }
+    if (l < lmin)
+        return (c1[0] > c2[0]);
+
+    return (l1 > l2);
+}
+
+int compare(const UString& s1, const UString& s2)
+{
+    const int l1 = s1.size();
+    const int l2 = s2.size();
+    const int lmin = l1 < l2 ? l1 : l2;
+    const UChar* c1 = s1.data();
+    const UChar* c2 = s2.data();
+    int l = 0;
+    while (l < lmin && *c1 == *c2) {
+        c1++;
+        c2++;
+        l++;
+    }
+
+    if (l < lmin)
+        return (c1[0] > c2[0]) ? 1 : -1;
+
+    if (l1 == l2)
+        return 0;
+
+    return (l1 > l2) ? 1 : -1;
+}
+
+bool equal(const UString::Rep* r, const UString::Rep* b)
+{
+    int length = r->len;
+    if (length != b->len)
+        return false;
+    const UChar* d = r->data();
+    const UChar* s = b->data();
+    for (int i = 0; i != length; ++i) {
+        if (d[i] != s[i])
+            return false;
+    }
+    return true;
+}
+
+CString UString::UTF8String(bool strict) const
+{
+    // Allocate a buffer big enough to hold all the characters.
+    const int length = size();
+    Vector<char, 1024> buffer(length * 3);
+
+    // Convert to runs of 8-bit characters.
+    char* p = buffer.data();
+    const UChar* d = reinterpret_cast<const UChar*>(&data()[0]);
+    ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict);
+    if (result != conversionOK)
+        return CString();
+
+    return CString(buffer.data(), p - buffer.data());
+}
+
+// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
+NEVER_INLINE void UString::makeNull()
+{
+    m_rep = &Rep::null;
+}
+
+// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.
+NEVER_INLINE UString::Rep* UString::nullRep()
+{
+    return &Rep::null;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/UString.h b/JavaScriptCore/runtime/UString.h
new file mode 100644
index 0000000..b964849
--- /dev/null
+++ b/JavaScriptCore/runtime/UString.h
@@ -0,0 +1,385 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2004, 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 _KJS_USTRING_H_
+#define _KJS_USTRING_H_
+
+#include "Collector.h"
+#include <stdint.h>
+#include <string.h>
+#include <wtf/Assertions.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC {
+
+    using WTF::PlacementNewAdoptType;
+    using WTF::PlacementNewAdopt;
+
+    class IdentifierTable;
+  
+    class CString {
+    public:
+        CString()
+            : m_length(0)
+            , m_data(0)
+        {
+        }
+
+        CString(const char*);
+        CString(const char*, size_t);
+        CString(const CString&);
+
+        ~CString();
+
+        static CString adopt(char*, size_t); // buffer should be allocated with new[].
+
+        CString& append(const CString&);
+        CString& operator=(const char* c);
+        CString& operator=(const CString&);
+        CString& operator+=(const CString& c) { return append(c); }
+
+        size_t size() const { return m_length; }
+        const char* c_str() const { return m_data; }
+
+    private:
+        size_t m_length;
+        char* m_data;
+    };
+
+    typedef Vector<char, 32> CStringBuffer;
+
+    class UString {
+        friend class CTI;
+
+    public:
+        struct Rep {
+            friend class CTI;
+
+            static PassRefPtr<Rep> create(UChar*, int);
+            static PassRefPtr<Rep> createCopying(const UChar*, int);
+            static PassRefPtr<Rep> create(PassRefPtr<Rep> base, int offset, int length);
+
+            // Constructs a string from a UTF-8 string, using strict conversion (see comments in UTF8.h).
+            // Returns UString::Rep::null for null input or conversion failure.
+            static PassRefPtr<Rep> createFromUTF8(const char*);
+
+            void destroy();
+
+            bool baseIsSelf() const { return baseString == this; }
+            UChar* data() const { return baseString->buf + baseString->preCapacity + offset; }
+            int size() const { return len; }
+
+            unsigned hash() const { if (_hash == 0) _hash = computeHash(data(), len); return _hash; }
+            unsigned computedHash() const { ASSERT(_hash); return _hash; } // fast path for Identifiers
+
+            static unsigned computeHash(const UChar*, int length);
+            static unsigned computeHash(const char*, int length);
+            static unsigned computeHash(const char* s) { return computeHash(s, strlen(s)); }
+
+            IdentifierTable* identifierTable() const { return reinterpret_cast<IdentifierTable*>(m_identifierTable & ~static_cast<uintptr_t>(1)); }
+            void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTable = reinterpret_cast<intptr_t>(table); }
+
+            bool isStatic() const { return m_identifierTable & 1; }
+            void setStatic(bool v) { ASSERT(!identifierTable()); m_identifierTable = v; }
+
+            Rep* ref() { ++rc; return this; }
+            ALWAYS_INLINE void deref() { if (--rc == 0) destroy(); }
+
+            void checkConsistency() const;
+
+            // unshared data
+            int offset;
+            int len;
+            int rc; // For null and empty static strings, this field does not reflect a correct count, because ref/deref are not thread-safe. A special case in destroy() guarantees that these do not get deleted.
+            mutable unsigned _hash;
+            intptr_t m_identifierTable; // A pointer to identifier table. The lowest bit is used to indicate whether the string is static (null or empty).
+            UString::Rep* baseString;
+            size_t reportedCost;
+
+            // potentially shared data. 0 if backed up by a base string.
+            UChar* buf;
+            int usedCapacity;
+            int capacity;
+            int usedPreCapacity;
+            int preCapacity;
+
+            static Rep null;
+            static Rep empty;
+        };
+
+    public:
+        UString();
+        UString(const char*);
+        UString(const UChar*, int length);
+        UString(UChar*, int length, bool copy);
+
+        UString(const UString& s)
+            : m_rep(s.m_rep)
+        {
+        }
+
+        UString(const Vector<UChar>& buffer);
+
+        ~UString()
+        {
+        }
+
+        // Special constructor for cases where we overwrite an object in place.
+        UString(PlacementNewAdoptType)
+            : m_rep(PlacementNewAdopt)
+        {
+        }
+
+        static UString from(int);
+        static UString from(unsigned int);
+        static UString from(long);
+        static UString from(double);
+
+        struct Range {
+        public:
+            Range(int pos, int len)
+                : position(pos)
+                , length(len)
+            {
+            }
+
+            Range()
+            {
+            }
+
+            int position;
+            int length;
+        };
+
+        UString spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const;
+
+        UString& append(const UString&);
+        UString& append(const char*);
+        UString& append(UChar);
+        UString& append(char c) { return append(static_cast<UChar>(static_cast<unsigned char>(c))); }
+        UString& append(const UChar*, int size);
+
+        bool getCString(CStringBuffer&) const;
+
+        // NOTE: This method should only be used for *debugging* purposes as it
+        // is neither Unicode safe nor free from side effects nor thread-safe.
+        char* ascii() const;
+
+        /**
+         * Convert the string to UTF-8, assuming it is UTF-16 encoded.
+         * In non-strict mode, this function is tolerant of badly formed UTF-16, it
+         * can create UTF-8 strings that are invalid because they have characters in
+         * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is
+         * guaranteed to be otherwise valid.
+         * In strict mode, error is returned as null CString.
+         */
+        CString UTF8String(bool strict = false) const;
+
+        UString& operator=(const char*c);
+
+        UString& operator+=(const UString& s) { return append(s); }
+        UString& operator+=(const char* s) { return append(s); }
+
+        const UChar* data() const { return m_rep->data(); }
+
+        bool isNull() const { return (m_rep == &Rep::null); }
+        bool isEmpty() const { return (!m_rep->len); }
+
+        bool is8Bit() const;
+
+        int size() const { return m_rep->size(); }
+
+        UChar operator[](int pos) const;
+
+        double toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const;
+        double toDouble(bool tolerateTrailingJunk) const;
+        double toDouble() const;
+
+        uint32_t toUInt32(bool* ok = 0) const;
+        uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const;
+        uint32_t toStrictUInt32(bool* ok = 0) const;
+
+        unsigned toArrayIndex(bool* ok = 0) const;
+
+        int find(const UString& f, int pos = 0) const;
+        int find(UChar, int pos = 0) const;
+        int rfind(const UString& f, int pos) const;
+        int rfind(UChar, int pos) const;
+
+        UString substr(int pos = 0, int len = -1) const;
+
+        static const UString& null();
+
+        Rep* rep() const { return m_rep.get(); }
+        static Rep* nullRep();
+
+        UString(PassRefPtr<Rep> r)
+            : m_rep(r)
+        {
+            ASSERT(m_rep);
+        }
+
+        size_t cost() const;
+
+    private:
+        int usedCapacity() const;
+        int usedPreCapacity() const;
+        void expandCapacity(int requiredLength);
+        void expandPreCapacity(int requiredPreCap);
+        void makeNull();
+
+        RefPtr<Rep> m_rep;
+
+        friend bool operator==(const UString&, const UString&);
+        friend PassRefPtr<Rep> concatenate(Rep*, Rep*); // returns 0 if out of memory
+    };
+    PassRefPtr<UString::Rep> concatenate(UString::Rep*, UString::Rep*);
+    PassRefPtr<UString::Rep> concatenate(UString::Rep*, int);
+    PassRefPtr<UString::Rep> concatenate(UString::Rep*, double);
+
+    bool operator==(const UString&, const UString&);
+
+    inline bool operator!=(const UString& s1, const UString& s2)
+    {
+        return !JSC::operator==(s1, s2);
+    }
+
+    bool operator<(const UString& s1, const UString& s2);
+    bool operator>(const UString& s1, const UString& s2);
+
+    bool operator==(const UString& s1, const char* s2);
+
+    inline bool operator!=(const UString& s1, const char* s2)
+    {
+        return !JSC::operator==(s1, s2);
+    }
+
+    inline bool operator==(const char *s1, const UString& s2)
+    {
+        return operator==(s2, s1);
+    }
+
+    inline bool operator!=(const char *s1, const UString& s2)
+    {
+        return !JSC::operator==(s1, s2);
+    }
+
+    bool operator==(const CString&, const CString&);
+
+    inline UString operator+(const UString& s1, const UString& s2)
+    {
+        RefPtr<UString::Rep> result = concatenate(s1.rep(), s2.rep());
+        return UString(result ? result.release() : UString::nullRep());
+    }
+
+    int compare(const UString&, const UString&);
+
+    bool equal(const UString::Rep*, const UString::Rep*);
+
+#ifdef NDEBUG
+    inline void UString::Rep::checkConsistency() const
+    {
+    }
+#endif
+
+    inline UString::UString()
+        : m_rep(&Rep::null)
+    {
+    }
+
+    // Rule from ECMA 15.2 about what an array index is.
+    // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
+    inline unsigned UString::toArrayIndex(bool* ok) const
+    {
+        unsigned i = toStrictUInt32(ok);
+        if (ok && i >= 0xFFFFFFFFU)
+            *ok = false;
+        return i;
+    }
+
+    // We'd rather not do shared substring append for small strings, since
+    // this runs too much risk of a tiny initial string holding down a
+    // huge buffer.
+    // FIXME: this should be size_t but that would cause warnings until we
+    // fix UString sizes to be size_t instead of int
+    static const int minShareSize = Heap::minExtraCostSize / sizeof(UChar);
+
+    inline size_t UString::cost() const
+    {
+        size_t capacity = (m_rep->baseString->capacity + m_rep->baseString->preCapacity) * sizeof(UChar);
+        size_t reportedCost = m_rep->baseString->reportedCost;
+        ASSERT(capacity >= reportedCost);
+
+        size_t capacityDelta = capacity - reportedCost;
+
+        if (capacityDelta < static_cast<size_t>(minShareSize))
+            return 0;
+
+        m_rep->baseString->reportedCost = capacity;
+
+        return capacityDelta;
+    }
+
+    struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > {
+        static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->computedHash(); }
+        static unsigned hash(JSC::UString::Rep* key) { return key->computedHash(); }
+    };
+
+} // namespace JSC
+
+namespace WTF {
+
+    template<typename T> struct DefaultHash;
+    template<typename T> struct StrHash;
+
+    template<> struct StrHash<JSC::UString::Rep*> {
+        static unsigned hash(const JSC::UString::Rep* key) { return key->hash(); }
+        static bool equal(const JSC::UString::Rep* a, const JSC::UString::Rep* b) { return JSC::equal(a, b); }
+        static const bool safeToCompareToEmptyOrDeleted = false;
+    };
+
+    template<> struct StrHash<RefPtr<JSC::UString::Rep> > : public StrHash<JSC::UString::Rep*> {
+        using StrHash<JSC::UString::Rep*>::hash;
+        static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->hash(); }
+        using StrHash<JSC::UString::Rep*>::equal;
+        static bool equal(const RefPtr<JSC::UString::Rep>& a, const RefPtr<JSC::UString::Rep>& b) { return JSC::equal(a.get(), b.get()); }
+        static bool equal(const JSC::UString::Rep* a, const RefPtr<JSC::UString::Rep>& b) { return JSC::equal(a, b.get()); }
+        static bool equal(const RefPtr<JSC::UString::Rep>& a, const JSC::UString::Rep* b) { return JSC::equal(a.get(), b); }
+
+        static const bool safeToCompareToEmptyOrDeleted = false;
+    };
+
+    template<> struct DefaultHash<JSC::UString::Rep*> {
+        typedef StrHash<JSC::UString::Rep*> Hash;
+    };
+
+    template<> struct DefaultHash<RefPtr<JSC::UString::Rep> > {
+        typedef StrHash<RefPtr<JSC::UString::Rep> > Hash;
+
+    };
+
+} // namespace WTF
+
+#endif