]> git.saurik.com Git - apple/javascriptcore.git/commitdiff
JavaScriptCore-576.tar.gz ios-40 v576
authorApple <opensource@apple.com>
Mon, 26 Jul 2010 21:27:40 +0000 (21:27 +0000)
committerApple <opensource@apple.com>
Mon, 26 Jul 2010 21:27:40 +0000 (21:27 +0000)
422 files changed:
API/APICast.h
API/APIShims.h [new file with mode: 0644]
API/JSBase.cpp
API/JSBase.h
API/JSCallbackConstructor.cpp
API/JSCallbackConstructor.h
API/JSCallbackFunction.cpp
API/JSCallbackFunction.h
API/JSCallbackObject.h
API/JSCallbackObjectFunctions.h
API/JSClassRef.cpp
API/JSClassRef.h
API/JSContextRef.cpp
API/JSContextRefPrivate.h [new file with mode: 0644]
API/JSObjectRef.cpp
API/JSStringRef.h
API/JSValueRef.cpp
API/OpaqueJSString.cpp
API/tests/testapi.c
API/tests/testapi.js
AllInOneFile.cpp
Android.mk [new file with mode: 0644]
Android.v8.wtf.mk [new file with mode: 0644]
DerivedSources.pro [new file with mode: 0644]
GNUmakefile.am
Info.plist
JavaScriptCore.exp
JavaScriptCore.gyp/JavaScriptCore.gyp [new file with mode: 0644]
JavaScriptCore.gypi
JavaScriptCore.iPhone.order
JavaScriptCore.order
JavaScriptCore.pri
JavaScriptCore.pro
JavaScriptCoreSources.bkl
assembler/ARMAssembler.cpp [new file with mode: 0644]
assembler/ARMAssembler.h [new file with mode: 0644]
assembler/ARMv7Assembler.h
assembler/AbstractMacroAssembler.h
assembler/AssemblerBufferWithConstantPool.h
assembler/MacroAssembler.h
assembler/MacroAssemblerARM.cpp [new file with mode: 0644]
assembler/MacroAssemblerARM.h [new file with mode: 0644]
assembler/MacroAssemblerARMv7.h
assembler/MacroAssemblerCodeRef.h
assembler/MacroAssemblerX86.h
assembler/MacroAssemblerX86Common.h
assembler/MacroAssemblerX86_64.h
assembler/X86Assembler.h
bytecode/CodeBlock.cpp
bytecode/CodeBlock.h
bytecode/EvalCodeCache.h
bytecode/Instruction.h
bytecode/Opcode.h
bytecode/SamplingTool.cpp
bytecode/SamplingTool.h
bytecode/StructureStubInfo.cpp
bytecode/StructureStubInfo.h
bytecompiler/BytecodeGenerator.cpp
bytecompiler/BytecodeGenerator.h
bytecompiler/Label.h
bytecompiler/NodesCodegen.cpp [new file with mode: 0644]
bytecompiler/RegisterID.h
config.h
create_rvct_stubs [new file with mode: 0644]
debugger/Debugger.cpp
debugger/Debugger.h
debugger/DebuggerActivation.cpp
debugger/DebuggerActivation.h
debugger/DebuggerCallFrame.cpp
interpreter/CachedCall.h
interpreter/CallFrame.h
interpreter/CallFrameClosure.h
interpreter/Interpreter.cpp
interpreter/Interpreter.h
interpreter/Register.h
interpreter/RegisterFile.cpp
interpreter/RegisterFile.h
jit/ExecutableAllocator.h
jit/ExecutableAllocatorFixedVMPool.cpp
jit/ExecutableAllocatorPosix.cpp
jit/ExecutableAllocatorSymbian.cpp [new file with mode: 0644]
jit/ExecutableAllocatorWin.cpp
jit/JIT.cpp
jit/JIT.h
jit/JITArithmetic.cpp
jit/JITCall.cpp
jit/JITCode.h
jit/JITInlineMethods.h
jit/JITOpcodes.cpp
jit/JITPropertyAccess.cpp
jit/JITStubCall.h
jit/JITStubs.cpp
jit/JITStubs.h
jsc.cpp
jsc.pro
jscore.bkl
os-win32/WinMain.cpp [new file with mode: 0644]
os-win32/stdbool.h
os-win32/stdint.h
parser/Grammar.y
parser/Lexer.cpp
parser/Lexer.h
parser/NodeConstructors.h
parser/Nodes.cpp
parser/Nodes.h
parser/Parser.cpp
parser/Parser.h
parser/ParserArena.cpp
parser/ParserArena.h
parser/SourceCode.h
pcre/dftables
pcre/pcre.pri
pcre/pcre_exec.cpp
profiler/HeavyProfile.cpp [deleted file]
profiler/HeavyProfile.h [deleted file]
profiler/ProfileGenerator.cpp
profiler/ProfileGenerator.h
profiler/ProfileNode.cpp
profiler/Profiler.cpp
profiler/Profiler.h
profiler/ProfilerServer.mm
profiler/TreeProfile.cpp [deleted file]
profiler/TreeProfile.h [deleted file]
qt/api/QtScript.pro [new file with mode: 0644]
qt/api/qscriptconverter_p.h [new file with mode: 0644]
qt/api/qscriptengine.cpp [new file with mode: 0644]
qt/api/qscriptengine.h [new file with mode: 0644]
qt/api/qscriptengine_p.cpp [new file with mode: 0644]
qt/api/qscriptengine_p.h [new file with mode: 0644]
qt/api/qscriptvalue.cpp [new file with mode: 0644]
qt/api/qscriptvalue.h [new file with mode: 0644]
qt/api/qscriptvalue_p.h [new file with mode: 0644]
qt/api/qtscriptglobal.h [new file with mode: 0644]
qt/tests/qscriptengine/qscriptengine.pro [new file with mode: 0644]
qt/tests/qscriptengine/tst_qscriptengine.cpp [new file with mode: 0644]
qt/tests/qscriptvalue/qscriptvalue.pro [new file with mode: 0644]
qt/tests/qscriptvalue/tst_qscriptvalue.cpp [new file with mode: 0644]
qt/tests/tests.pri [new file with mode: 0644]
qt/tests/tests.pro [new file with mode: 0644]
runtime/ArgList.cpp
runtime/ArgList.h
runtime/Arguments.cpp
runtime/Arguments.h
runtime/ArrayConstructor.cpp
runtime/ArrayConstructor.h
runtime/ArrayPrototype.cpp
runtime/ArrayPrototype.h
runtime/BatchedTransitionOptimizer.h
runtime/BooleanConstructor.cpp
runtime/BooleanConstructor.h
runtime/BooleanObject.cpp
runtime/BooleanObject.h
runtime/BooleanPrototype.cpp
runtime/BooleanPrototype.h
runtime/CallData.h
runtime/ClassInfo.h
runtime/Collector.cpp
runtime/Collector.h
runtime/CollectorHeapIterator.h
runtime/CommonIdentifiers.h
runtime/Completion.cpp
runtime/ConstructData.h
runtime/DateConstructor.cpp
runtime/DateConstructor.h
runtime/DateConversion.cpp
runtime/DateConversion.h
runtime/DateInstance.cpp
runtime/DateInstance.h
runtime/DateInstanceCache.h [new file with mode: 0644]
runtime/DatePrototype.cpp
runtime/DatePrototype.h
runtime/Error.cpp
runtime/Error.h
runtime/ErrorConstructor.cpp
runtime/ErrorConstructor.h
runtime/ErrorInstance.cpp
runtime/ErrorInstance.h
runtime/ErrorPrototype.cpp
runtime/ErrorPrototype.h
runtime/ExceptionHelpers.cpp
runtime/ExceptionHelpers.h
runtime/Executable.cpp [new file with mode: 0644]
runtime/Executable.h [new file with mode: 0644]
runtime/FunctionConstructor.cpp
runtime/FunctionConstructor.h
runtime/FunctionPrototype.cpp
runtime/FunctionPrototype.h
runtime/GetterSetter.cpp
runtime/GetterSetter.h
runtime/GlobalEvalFunction.cpp
runtime/GlobalEvalFunction.h
runtime/Identifier.cpp
runtime/Identifier.h
runtime/InitializeThreading.cpp
runtime/InternalFunction.cpp
runtime/InternalFunction.h
runtime/JSAPIValueWrapper.cpp
runtime/JSAPIValueWrapper.h
runtime/JSActivation.cpp
runtime/JSActivation.h
runtime/JSArray.cpp
runtime/JSArray.h
runtime/JSByteArray.cpp
runtime/JSByteArray.h
runtime/JSCell.cpp
runtime/JSCell.h
runtime/JSFunction.cpp
runtime/JSFunction.h
runtime/JSGlobalData.cpp
runtime/JSGlobalData.h
runtime/JSGlobalObject.cpp
runtime/JSGlobalObject.h
runtime/JSGlobalObjectFunctions.cpp
runtime/JSLock.cpp
runtime/JSLock.h
runtime/JSNotAnObject.cpp
runtime/JSNotAnObject.h
runtime/JSNumberCell.cpp
runtime/JSNumberCell.h
runtime/JSONObject.cpp
runtime/JSONObject.h
runtime/JSObject.cpp
runtime/JSObject.h
runtime/JSPropertyNameIterator.cpp
runtime/JSPropertyNameIterator.h
runtime/JSStaticScopeObject.cpp
runtime/JSStaticScopeObject.h
runtime/JSString.cpp
runtime/JSString.h
runtime/JSType.h
runtime/JSTypeInfo.h [new file with mode: 0644]
runtime/JSValue.cpp
runtime/JSValue.h
runtime/JSVariableObject.cpp
runtime/JSVariableObject.h
runtime/JSWrapperObject.cpp
runtime/JSWrapperObject.h
runtime/JSZombie.cpp [new file with mode: 0644]
runtime/JSZombie.h [new file with mode: 0644]
runtime/LiteralParser.cpp
runtime/LiteralParser.h
runtime/Lookup.cpp
runtime/Lookup.h
runtime/MarkStack.cpp [new file with mode: 0644]
runtime/MarkStack.h [new file with mode: 0644]
runtime/MarkStackNone.cpp [new file with mode: 0644]
runtime/MarkStackPosix.cpp [new file with mode: 0644]
runtime/MarkStackSymbian.cpp [new file with mode: 0644]
runtime/MarkStackWin.cpp [new file with mode: 0644]
runtime/MathObject.cpp
runtime/MathObject.h
runtime/NativeErrorConstructor.cpp
runtime/NativeErrorConstructor.h
runtime/NativeErrorPrototype.cpp
runtime/NativeErrorPrototype.h
runtime/NumberConstructor.cpp
runtime/NumberConstructor.h
runtime/NumberObject.cpp
runtime/NumberObject.h
runtime/NumberPrototype.cpp
runtime/NumberPrototype.h
runtime/NumericStrings.h [new file with mode: 0644]
runtime/ObjectConstructor.cpp
runtime/ObjectConstructor.h
runtime/ObjectPrototype.cpp
runtime/ObjectPrototype.h
runtime/Operations.cpp
runtime/Operations.h
runtime/PropertyDescriptor.cpp [new file with mode: 0644]
runtime/PropertyDescriptor.h [new file with mode: 0644]
runtime/PropertyNameArray.cpp
runtime/PropertyNameArray.h
runtime/PropertySlot.cpp
runtime/Protect.h
runtime/PrototypeFunction.cpp
runtime/PrototypeFunction.h
runtime/RegExp.cpp
runtime/RegExp.h
runtime/RegExpConstructor.cpp
runtime/RegExpConstructor.h
runtime/RegExpMatchesArray.h
runtime/RegExpObject.cpp
runtime/RegExpObject.h
runtime/RegExpPrototype.cpp
runtime/RegExpPrototype.h
runtime/ScopeChain.cpp
runtime/ScopeChain.h
runtime/ScopeChainMark.h
runtime/SmallStrings.cpp
runtime/SmallStrings.h
runtime/StringBuilder.h [new file with mode: 0644]
runtime/StringConstructor.cpp
runtime/StringConstructor.h
runtime/StringObject.cpp
runtime/StringObject.h
runtime/StringObjectThatMasqueradesAsUndefined.h
runtime/StringPrototype.cpp
runtime/StringPrototype.h
runtime/Structure.cpp
runtime/Structure.h
runtime/StructureChain.cpp
runtime/StructureChain.h
runtime/StructureTransitionTable.h
runtime/SymbolTable.h
runtime/TimeoutChecker.cpp
runtime/Tracing.d
runtime/Tracing.h
runtime/TypeInfo.h [deleted file]
runtime/UString.cpp
runtime/UString.h
runtime/UStringImpl.cpp [new file with mode: 0644]
runtime/UStringImpl.h [new file with mode: 0644]
runtime/WeakGCMap.h [new file with mode: 0644]
runtime/WeakGCPtr.h [new file with mode: 0644]
runtime/WeakRandom.h [new file with mode: 0644]
tests/mozilla/ecma/Date/15.9.5.10-1.js
tests/mozilla/ecma/Date/15.9.5.12-1.js
tests/mozilla/ecma_2/RegExp/properties-001.js
tests/mozilla/js1_2/regexp/toString.js
wrec/WREC.h
wrec/WRECGenerator.cpp
wrec/WRECGenerator.h
wscript [new file with mode: 0644]
wtf/AlwaysInline.h
wtf/Assertions.cpp
wtf/Assertions.h
wtf/ByteArray.h
wtf/CrossThreadRefCounted.h
wtf/CurrentTime.cpp
wtf/CurrentTime.h
wtf/DateMath.cpp
wtf/DateMath.h
wtf/DisallowCType.h
wtf/FastAllocBase.h
wtf/FastMalloc.cpp
wtf/FastMalloc.h
wtf/Forward.h
wtf/GOwnPtr.cpp [deleted file]
wtf/GOwnPtr.h [deleted file]
wtf/HashCountedSet.h
wtf/HashFunctions.h
wtf/HashMap.h
wtf/HashSet.h
wtf/HashTable.h
wtf/ListHashSet.h
wtf/ListRefPtr.h
wtf/Locker.h
wtf/MainThread.cpp
wtf/MainThread.h
wtf/MathExtras.h
wtf/MessageQueue.h
wtf/Noncopyable.h
wtf/OwnArrayPtr.h
wtf/OwnFastMallocPtr.h
wtf/OwnPtr.h
wtf/PassRefPtr.h
wtf/Platform.h
wtf/PossiblyNull.h [new file with mode: 0644]
wtf/PtrAndFlags.h
wtf/RandomNumber.cpp
wtf/RandomNumberSeed.h
wtf/RefCounted.h
wtf/RefPtr.h
wtf/RefPtrHashMap.h
wtf/SegmentedVector.h
wtf/StdLibExtras.h
wtf/StringExtras.cpp [new file with mode: 0644]
wtf/StringExtras.h
wtf/StringHashFunctions.h [new file with mode: 0644]
wtf/TCSpinLock.h
wtf/TCSystemAlloc.cpp
wtf/ThreadIdentifierDataPthreads.cpp [new file with mode: 0644]
wtf/ThreadIdentifierDataPthreads.h [new file with mode: 0644]
wtf/ThreadSpecific.h
wtf/Threading.cpp
wtf/Threading.h
wtf/ThreadingNone.cpp
wtf/ThreadingPthreads.cpp
wtf/ThreadingWin.cpp
wtf/TypeTraits.cpp
wtf/TypeTraits.h
wtf/VMTags.h
wtf/ValueCheck.h [new file with mode: 0644]
wtf/Vector.h
wtf/VectorTraits.h
wtf/android/AndroidThreading.h [new file with mode: 0644]
wtf/android/MainThreadAndroid.cpp [new file with mode: 0644]
wtf/chromium/ChromiumThreading.h
wtf/dtoa.cpp
wtf/dtoa.h
wtf/gtk/GOwnPtr.cpp [new file with mode: 0644]
wtf/gtk/GOwnPtr.h [new file with mode: 0644]
wtf/gtk/GRefPtr.cpp [new file with mode: 0644]
wtf/gtk/GRefPtr.h [new file with mode: 0644]
wtf/gtk/ThreadingGtk.cpp
wtf/haiku/MainThreadHaiku.cpp [new file with mode: 0644]
wtf/iphone/MainThreadIPhone.mm [deleted file]
wtf/iphone/WebCoreThread.cpp [new file with mode: 0644]
wtf/iphone/WebCoreThread.h [new file with mode: 0644]
wtf/mac/MainThreadMac.mm
wtf/qt/ThreadingQt.cpp
wtf/unicode/Collator.h
wtf/unicode/UTF8.cpp
wtf/unicode/Unicode.h
wtf/unicode/glib/UnicodeGLib.cpp
wtf/unicode/glib/UnicodeGLib.h
wtf/unicode/icu/CollatorICU.cpp
wtf/unicode/icu/UnicodeIcu.h
wtf/unicode/qt4/UnicodeQt4.h
wtf/unicode/wince/UnicodeWince.cpp [new file with mode: 0644]
wtf/unicode/wince/UnicodeWince.h [new file with mode: 0644]
wtf/win/MainThreadWin.cpp
wtf/wince/FastMallocWince.h [new file with mode: 0644]
wtf/wince/MemoryManager.cpp [new file with mode: 0644]
wtf/wince/MemoryManager.h [new file with mode: 0644]
wtf/wince/mt19937ar.c [new file with mode: 0644]
yarr/RegexCompiler.cpp
yarr/RegexInterpreter.cpp
yarr/RegexInterpreter.h
yarr/RegexJIT.cpp
yarr/RegexJIT.h
yarr/RegexPattern.h

index b6d15320aab3badfe0d650d80f09b57132378e2e..4284c448a05593c2ee569660a3c839ea05ea969f 100644 (file)
@@ -27,6 +27,7 @@
 #define APICast_h
 
 #include "JSAPIValueWrapper.h"
 #define APICast_h
 
 #include "JSAPIValueWrapper.h"
+#include "JSGlobalObject.h"
 #include "JSValue.h"
 #include <wtf/Platform.h>
 #include <wtf/UnusedParam.h>
 #include "JSValue.h"
 #include <wtf/Platform.h>
 #include <wtf/UnusedParam.h>
@@ -50,16 +51,20 @@ typedef struct OpaqueJSValue* JSObjectRef;
 
 inline JSC::ExecState* toJS(JSContextRef c)
 {
 
 inline JSC::ExecState* toJS(JSContextRef c)
 {
+    ASSERT(c);
     return reinterpret_cast<JSC::ExecState*>(const_cast<OpaqueJSContext*>(c));
 }
 
 inline JSC::ExecState* toJS(JSGlobalContextRef c)
 {
     return reinterpret_cast<JSC::ExecState*>(const_cast<OpaqueJSContext*>(c));
 }
 
 inline JSC::ExecState* toJS(JSGlobalContextRef c)
 {
+    ASSERT(c);
     return reinterpret_cast<JSC::ExecState*>(c);
 }
 
     return reinterpret_cast<JSC::ExecState*>(c);
 }
 
-inline JSC::JSValue toJS(JSC::ExecState*, JSValueRef v)
+inline JSC::JSValue toJS(JSC::ExecState* exec, JSValueRef v)
 {
 {
+    ASSERT_UNUSED(exec, exec);
+    ASSERT(v);
 #if USE(JSVALUE32_64)
     JSC::JSCell* jsCell = reinterpret_cast<JSC::JSCell*>(const_cast<OpaqueJSValue*>(v));
     if (!jsCell)
 #if USE(JSVALUE32_64)
     JSC::JSCell* jsCell = reinterpret_cast<JSC::JSCell*>(const_cast<OpaqueJSValue*>(v));
     if (!jsCell)
@@ -72,6 +77,20 @@ inline JSC::JSValue toJS(JSC::ExecState*, JSValueRef v)
 #endif
 }
 
 #endif
 }
 
+inline JSC::JSValue toJSForGC(JSC::ExecState* exec, JSValueRef v)
+{
+    ASSERT_UNUSED(exec, exec);
+    ASSERT(v);
+#if USE(JSVALUE32_64)
+    JSC::JSCell* jsCell = reinterpret_cast<JSC::JSCell*>(const_cast<OpaqueJSValue*>(v));
+    if (!jsCell)
+        return JSC::JSValue();
+    return jsCell;
+#else
+    return JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(const_cast<OpaqueJSValue*>(v)));
+#endif
+}
+
 inline JSC::JSObject* toJS(JSObjectRef o)
 {
     return reinterpret_cast<JSC::JSObject*>(o);
 inline JSC::JSObject* toJS(JSObjectRef o)
 {
     return reinterpret_cast<JSC::JSObject*>(o);
@@ -118,6 +137,7 @@ inline JSContextRef toRef(JSC::ExecState* e)
 
 inline JSGlobalContextRef toGlobalRef(JSC::ExecState* e)
 {
 
 inline JSGlobalContextRef toGlobalRef(JSC::ExecState* e)
 {
+    ASSERT(e == e->lexicalGlobalObject()->globalExec());
     return reinterpret_cast<JSGlobalContextRef>(e);
 }
 
     return reinterpret_cast<JSGlobalContextRef>(e);
 }
 
diff --git a/API/APIShims.h b/API/APIShims.h
new file mode 100644 (file)
index 0000000..d7276ec
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 APIShims_h
+#define APIShims_h
+
+#include "CallFrame.h"
+#include "JSLock.h"
+
+namespace JSC {
+
+class APIEntryShimWithoutLock {
+protected:
+    APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread)
+        : m_globalData(globalData)
+        , m_entryIdentifierTable(setCurrentIdentifierTable(globalData->identifierTable))
+    {
+        if (registerThread)
+            globalData->heap.registerThread();
+        m_globalData->timeoutChecker.start();
+    }
+
+    ~APIEntryShimWithoutLock()
+    {
+        m_globalData->timeoutChecker.stop();
+        setCurrentIdentifierTable(m_entryIdentifierTable);
+    }
+
+private:
+    JSGlobalData* m_globalData;
+    IdentifierTable* m_entryIdentifierTable;
+};
+
+class APIEntryShim : public APIEntryShimWithoutLock {
+public:
+    // Normal API entry
+    APIEntryShim(ExecState* exec, bool registerThread = true)
+        : APIEntryShimWithoutLock(&exec->globalData(), registerThread)
+        , m_lock(exec)
+    {
+    }
+
+    // JSPropertyNameAccumulator only has a globalData.
+    APIEntryShim(JSGlobalData* globalData, bool registerThread = true)
+        : APIEntryShimWithoutLock(globalData, registerThread)
+        , m_lock(globalData->isSharedInstance ? LockForReal : SilenceAssertionsOnly)
+    {
+    }
+
+private:
+    JSLock m_lock;
+};
+
+class APICallbackShim {
+public:
+    APICallbackShim(ExecState* exec)
+        : m_dropAllLocks(exec)
+        , m_globalData(&exec->globalData())
+    {
+        resetCurrentIdentifierTable();
+        m_globalData->timeoutChecker.start();
+    }
+
+    ~APICallbackShim()
+    {
+        m_globalData->timeoutChecker.stop();
+        setCurrentIdentifierTable(m_globalData->identifierTable);
+    }
+
+private:
+    JSLock::DropAllLocks m_dropAllLocks;
+    JSGlobalData* m_globalData;
+};
+
+}
+
+#endif
index fc3d0fe1bcbe8707232390a9f23cc1cfc67a2b7a..ebfeafa820a7e703fa59b27d8e7631f126e5ae49 100644 (file)
@@ -28,6 +28,7 @@
 #include "JSBasePrivate.h"
 
 #include "APICast.h"
 #include "JSBasePrivate.h"
 
 #include "APICast.h"
+#include "APIShims.h"
 #include "Completion.h"
 #include "OpaqueJSString.h"
 #include "SourceCode.h"
 #include "Completion.h"
 #include "OpaqueJSString.h"
 #include "SourceCode.h"
@@ -43,8 +44,7 @@ using namespace JSC;
 JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsThisObject = toJS(thisObject);
 
 
     JSObject* jsThisObject = toJS(thisObject);
 
@@ -69,8 +69,7 @@ JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef th
 bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber);
     Completion completion = checkSyntax(exec->dynamicGlobalObject()->globalExec(), source);
 
     SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber);
     Completion completion = checkSyntax(exec->dynamicGlobalObject()->globalExec(), source);
@@ -94,12 +93,11 @@ void JSGarbageCollect(JSContextRef ctx)
         return;
 
     ExecState* exec = toJS(ctx);
         return;
 
     ExecState* exec = toJS(ctx);
-    JSGlobalData& globalData = exec->globalData();
-
-    JSLock lock(globalData.isSharedInstance);
+    APIEntryShim entryShim(exec, false);
 
 
+    JSGlobalData& globalData = exec->globalData();
     if (!globalData.heap.isBusy())
     if (!globalData.heap.isBusy())
-        globalData.heap.collect();
+        globalData.heap.collectAllGarbage();
 
     // FIXME: Perhaps we should trigger a second mark and sweep
     // once the garbage collector is done if this is called when
 
     // FIXME: Perhaps we should trigger a second mark and sweep
     // once the garbage collector is done if this is called when
@@ -109,8 +107,6 @@ void JSGarbageCollect(JSContextRef ctx)
 void JSReportExtraMemoryCost(JSContextRef ctx, size_t size)
 {
     ExecState* exec = toJS(ctx);
 void JSReportExtraMemoryCost(JSContextRef ctx, size_t size)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
-
+    APIEntryShim entryShim(exec);
     exec->globalData().heap.reportExtraMemoryCost(size);
 }
     exec->globalData().heap.reportExtraMemoryCost(size);
 }
index 9f3d88eb18ff457eae53766345d560ac57af8809..2e16720cebb18a822179b9ae3fded3d069161315 100644 (file)
@@ -65,27 +65,15 @@ typedef struct OpaqueJSValue* JSObjectRef;
 /* JavaScript symbol exports */
 
 #undef JS_EXPORT
 /* JavaScript symbol exports */
 
 #undef JS_EXPORT
-#if defined(BUILDING_WX__)
+#if defined(JS_NO_EXPORT)
     #define JS_EXPORT
     #define JS_EXPORT
-#elif defined(__GNUC__)
+#elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__)
     #define JS_EXPORT __attribute__((visibility("default")))
     #define JS_EXPORT __attribute__((visibility("default")))
-#elif defined(_WIN32_WCE)
-    #if defined(JS_BUILDING_JS)
-        #define JS_EXPORT __declspec(dllexport)
-    #elif defined(JS_IMPORT_JS)
-        #define JS_EXPORT __declspec(dllimport)
-    #else
-        #define JS_EXPORT
-    #endif
-#elif defined(WIN32) || defined(_WIN32)
-    /*
-     * TODO: Export symbols with JS_EXPORT when using MSVC.
-     * See http://bugs.webkit.org/show_bug.cgi?id=16227
-     */
+#elif defined(WIN32) || defined(_WIN32) || defined(_WIN32_WCE)
     #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
     #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
-    #define JS_EXPORT __declspec(dllexport)
+        #define JS_EXPORT __declspec(dllexport)
     #else
     #else
-    #define JS_EXPORT __declspec(dllimport)
+        #define JS_EXPORT __declspec(dllimport)
     #endif
 #else
     #define JS_EXPORT
     #endif
 #else
     #define JS_EXPORT
index 64c83cb04df1496284d1a2586c4442d6eee1f5e5..9c5f6d73e6e1ab66503fd177f6817400a399335b 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "JSCallbackConstructor.h"
 
 #include "config.h"
 #include "JSCallbackConstructor.h"
 
+#include "APIShims.h"
 #include "APICast.h"
 #include <runtime/JSGlobalObject.h>
 #include <runtime/JSLock.h>
 #include "APICast.h"
 #include <runtime/JSGlobalObject.h>
 #include <runtime/JSLock.h>
@@ -36,7 +37,7 @@ namespace JSC {
 
 const ClassInfo JSCallbackConstructor::info = { "CallbackConstructor", 0, 0, 0 };
 
 
 const ClassInfo JSCallbackConstructor::info = { "CallbackConstructor", 0, 0, 0 };
 
-JSCallbackConstructor::JSCallbackConstructor(PassRefPtr<Structure> structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback)
+JSCallbackConstructor::JSCallbackConstructor(NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback)
     : JSObject(structure)
     , m_class(jsClass)
     , m_callback(callback)
     : JSObject(structure)
     , m_class(jsClass)
     , m_callback(callback)
@@ -66,7 +67,7 @@ static JSObject* constructJSCallback(ExecState* exec, JSObject* constructor, con
         JSValueRef exception = 0;
         JSObjectRef result;
         {
         JSValueRef exception = 0;
         JSObjectRef result;
         {
-            JSLock::DropAllLocks dropAllLocks(exec);
+            APICallbackShim callbackShim(exec);
             result = callback(ctx, constructorRef, argumentCount, arguments.data(), &exception);
         }
         if (exception)
             result = callback(ctx, constructorRef, argumentCount, arguments.data(), &exception);
         }
         if (exception)
index 1f0624911b9830bd65b22fd6219fc3a7f68028b7..e52994724e2fd0d4b9c290c5890bceccaeb2e923 100644 (file)
@@ -33,7 +33,7 @@ namespace JSC {
 
 class JSCallbackConstructor : public JSObject {
 public:
 
 class JSCallbackConstructor : public JSObject {
 public:
-    JSCallbackConstructor(PassRefPtr<Structure>, JSClassRef, JSObjectCallAsConstructorCallback);
+    JSCallbackConstructor(NonNullPassRefPtr<Structure>, JSClassRef, JSObjectCallAsConstructorCallback);
     virtual ~JSCallbackConstructor();
     JSClassRef classRef() const { return m_class; }
     JSObjectCallAsConstructorCallback callback() const { return m_callback; }
     virtual ~JSCallbackConstructor();
     JSClassRef classRef() const { return m_class; }
     JSObjectCallAsConstructorCallback callback() const { return m_callback; }
@@ -41,9 +41,12 @@ public:
     
     static PassRefPtr<Structure> createStructure(JSValue proto) 
     { 
     
     static PassRefPtr<Structure> createStructure(JSValue proto) 
     { 
-        return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot)); 
+        return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
     }
 
     }
 
+protected:
+    static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
+
 private:
     virtual ConstructType getConstructData(ConstructData&);
     virtual const ClassInfo* classInfo() const { return &info; }
 private:
     virtual ConstructType getConstructData(ConstructData&);
     virtual const ClassInfo* classInfo() const { return &info; }
index 1b3217b40416ca82dad19955b4a10358a2a42ca8..0e434d960eac8f692f85a05fe74bcff55a335896 100644 (file)
@@ -27,7 +27,9 @@
 #include <wtf/Platform.h>
 #include "JSCallbackFunction.h"
 
 #include <wtf/Platform.h>
 #include "JSCallbackFunction.h"
 
+#include "APIShims.h"
 #include "APICast.h"
 #include "APICast.h"
+#include "CodeBlock.h"
 #include "JSFunction.h"
 #include "FunctionPrototype.h"
 #include <runtime/JSGlobalObject.h>
 #include "JSFunction.h"
 #include "FunctionPrototype.h"
 #include <runtime/JSGlobalObject.h>
@@ -60,7 +62,7 @@ JSValue JSCallbackFunction::call(ExecState* exec, JSObject* functionObject, JSVa
     JSValueRef exception = 0;
     JSValueRef result;
     {
     JSValueRef exception = 0;
     JSValueRef result;
     {
-        JSLock::DropAllLocks dropAllLocks(exec);
+        APICallbackShim callbackShim(exec);
         result = static_cast<JSCallbackFunction*>(functionObject)->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception);
     }
     if (exception)
         result = static_cast<JSCallbackFunction*>(functionObject)->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception);
     }
     if (exception)
index 7dd87b59b58c5b9435969580bcc26cf05e50210a..10dae6b73f0437c8a68f743573deaf601e6fca8c 100644 (file)
@@ -41,7 +41,7 @@ public:
     // refactor the code so this override isn't necessary
     static PassRefPtr<Structure> createStructure(JSValue proto) 
     { 
     // refactor the code so this override isn't necessary
     static PassRefPtr<Structure> createStructure(JSValue proto) 
     { 
-        return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); 
+        return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
     }
 
 private:
     }
 
 private:
index 9d22ad91f0f42b9363ea1a40c0e304baa8bfd923..adb5b602a75e86fe99d055298c174fbefaf32414 100644 (file)
@@ -36,7 +36,7 @@ namespace JSC {
 template <class Base>
 class JSCallbackObject : public Base {
 public:
 template <class Base>
 class JSCallbackObject : public Base {
 public:
-    JSCallbackObject(ExecState*, PassRefPtr<Structure>, JSClassRef, void* data);
+    JSCallbackObject(ExecState*, NonNullPassRefPtr<Structure>, JSClassRef, void* data);
     JSCallbackObject(JSClassRef);
     virtual ~JSCallbackObject();
 
     JSCallbackObject(JSClassRef);
     virtual ~JSCallbackObject();
 
@@ -50,14 +50,18 @@ public:
 
     static PassRefPtr<Structure> createStructure(JSValue proto) 
     { 
 
     static PassRefPtr<Structure> createStructure(JSValue proto) 
     { 
-        return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | OverridesHasInstance)); 
+        return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), Base::AnonymousSlotCount); 
     }
 
     }
 
+protected:
+    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | Base::StructureFlags;
+
 private:
     virtual UString className() const;
 
     virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&);
 private:
     virtual UString className() const;
 
     virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&);
+    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
     
     virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
 
     
     virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
 
@@ -66,7 +70,7 @@ private:
 
     virtual bool hasInstance(ExecState* exec, JSValue value, JSValue proto);
 
 
     virtual bool hasInstance(ExecState* exec, JSValue value, JSValue proto);
 
-    virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+    virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
 
     virtual double toNumber(ExecState*) const;
     virtual UString toString(ExecState*) const;
 
     virtual double toNumber(ExecState*) const;
     virtual UString toString(ExecState*) const;
index 1abed3fb563608d82d0c8f1e5eba1017091bbd65..4b28a99285bdc2010e7d685569e9885cc403a1d2 100644 (file)
@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
+#include "APIShims.h"
 #include "APICast.h"
 #include "Error.h"
 #include "JSCallbackFunction.h"
 #include "APICast.h"
 #include "Error.h"
 #include "JSCallbackFunction.h"
@@ -47,7 +48,7 @@ inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValue
 }
 
 template <class Base>
 }
 
 template <class Base>
-JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, PassRefPtr<Structure> structure, JSClassRef jsClass, void* data)
+JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, void* data)
     : Base(structure)
     , m_callbackObjectData(new JSCallbackObjectData(data, jsClass))
 {
     : Base(structure)
     , m_callbackObjectData(new JSCallbackObjectData(data, jsClass))
 {
@@ -79,7 +80,7 @@ void JSCallbackObject<Base>::init(ExecState* exec)
     
     // initialize from base to derived
     for (int i = static_cast<int>(initRoutines.size()) - 1; i >= 0; i--) {
     
     // initialize from base to derived
     for (int i = static_cast<int>(initRoutines.size()) - 1; i >= 0; i--) {
-        JSLock::DropAllLocks dropAllLocks(exec);
+        APICallbackShim callbackShim(exec);
         JSObjectInitializeCallback initialize = initRoutines[i];
         initialize(toRef(exec), toRef(this));
     }
         JSObjectInitializeCallback initialize = initRoutines[i];
         initialize(toRef(exec), toRef(this));
     }
@@ -117,7 +118,7 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie
         if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
             if (!propertyNameRef)
                 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
         if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
             if (!propertyNameRef)
                 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
-            JSLock::DropAllLocks dropAllLocks(exec);
+            APICallbackShim callbackShim(exec);
             if (hasProperty(ctx, thisRef, propertyNameRef.get())) {
                 slot.setCustom(this, callbackGetter);
                 return true;
             if (hasProperty(ctx, thisRef, propertyNameRef.get())) {
                 slot.setCustom(this, callbackGetter);
                 return true;
@@ -128,18 +129,18 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie
             JSValueRef exception = 0;
             JSValueRef value;
             {
             JSValueRef exception = 0;
             JSValueRef value;
             {
-                JSLock::DropAllLocks dropAllLocks(exec);
+                APICallbackShim callbackShim(exec);
                 value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception);
             }
                 value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception);
             }
-            exec->setException(toJS(exec, exception));
-            if (value) {
-                slot.setValue(toJS(exec, value));
-                return true;
-            }
             if (exception) {
             if (exception) {
+                exec->setException(toJS(exec, exception));
                 slot.setValue(jsUndefined());
                 return true;
             }
                 slot.setValue(jsUndefined());
                 return true;
             }
+            if (value) {
+                slot.setValue(toJS(exec, value));
+                return true;
+            }
         }
         
         if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
         }
         
         if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
@@ -166,6 +167,25 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, unsigned proper
     return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
 }
 
     return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
 }
 
+template <class Base>
+bool JSCallbackObject<Base>::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    PropertySlot slot;
+    if (getOwnPropertySlot(exec, propertyName, slot)) {
+        // Ideally we should return an access descriptor, but returning a value descriptor is better than nothing.
+        JSValue value = slot.getValue(exec, propertyName);
+        if (!exec->hadException())
+            descriptor.setValue(value);
+        // We don't know whether the property is configurable, but assume it is.
+        descriptor.setConfigurable(true);
+        // We don't know whether the property is enumerable (we could call getOwnPropertyNames() to find out), but assume it isn't.
+        descriptor.setEnumerable(false);
+        return true;
+    }
+
+    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
 template <class Base>
 void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 template <class Base>
 void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
@@ -181,10 +201,11 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName
             JSValueRef exception = 0;
             bool result;
             {
             JSValueRef exception = 0;
             bool result;
             {
-                JSLock::DropAllLocks dropAllLocks(exec);
+                APICallbackShim callbackShim(exec);
                 result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
             }
                 result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
             }
-            exec->setException(toJS(exec, exception));
+            if (exception)
+                exec->setException(toJS(exec, exception));
             if (result || exception)
                 return;
         }
             if (result || exception)
                 return;
         }
@@ -199,10 +220,11 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName
                     JSValueRef exception = 0;
                     bool result;
                     {
                     JSValueRef exception = 0;
                     bool result;
                     {
-                        JSLock::DropAllLocks dropAllLocks(exec);
+                        APICallbackShim callbackShim(exec);
                         result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
                     }
                         result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
                     }
-                    exec->setException(toJS(exec, exception));
+                    if (exception)
+                        exec->setException(toJS(exec, exception));
                     if (result || exception)
                         return;
                 } else
                     if (result || exception)
                         return;
                 } else
@@ -237,10 +259,11 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p
             JSValueRef exception = 0;
             bool result;
             {
             JSValueRef exception = 0;
             bool result;
             {
-                JSLock::DropAllLocks dropAllLocks(exec);
+                APICallbackShim callbackShim(exec);
                 result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception);
             }
                 result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception);
             }
-            exec->setException(toJS(exec, exception));
+            if (exception)
+                exec->setException(toJS(exec, exception));
             if (result || exception)
                 return true;
         }
             if (result || exception)
                 return true;
         }
@@ -298,10 +321,11 @@ JSObject* JSCallbackObject<Base>::construct(ExecState* exec, JSObject* construct
             JSValueRef exception = 0;
             JSObject* result;
             {
             JSValueRef exception = 0;
             JSObject* result;
             {
-                JSLock::DropAllLocks dropAllLocks(exec);
+                APICallbackShim callbackShim(exec);
                 result = toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), &exception));
             }
                 result = toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), &exception));
             }
-            exec->setException(toJS(exec, exception));
+            if (exception)
+                exec->setException(toJS(exec, exception));
             return result;
         }
     }
             return result;
         }
     }
@@ -322,10 +346,11 @@ bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue value, JSValue
             JSValueRef exception = 0;
             bool result;
             {
             JSValueRef exception = 0;
             bool result;
             {
-                JSLock::DropAllLocks dropAllLocks(exec);
+                APICallbackShim callbackShim(exec);
                 result = hasInstance(execRef, thisRef, valueRef, &exception);
             }
                 result = hasInstance(execRef, thisRef, valueRef, &exception);
             }
-            exec->setException(toJS(exec, exception));
+            if (exception)
+                exec->setException(toJS(exec, exception));
             return result;
         }
     }
             return result;
         }
     }
@@ -360,10 +385,11 @@ JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject,
             JSValueRef exception = 0;
             JSValue result;
             {
             JSValueRef exception = 0;
             JSValue result;
             {
-                JSLock::DropAllLocks dropAllLocks(exec);
+                APICallbackShim callbackShim(exec);
                 result = toJS(exec, callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception));
             }
                 result = toJS(exec, callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception));
             }
-            exec->setException(toJS(exec, exception));
+            if (exception)
+                exec->setException(toJS(exec, exception));
             return result;
         }
     }
             return result;
         }
     }
@@ -373,14 +399,14 @@ JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject,
 }
 
 template <class Base>
 }
 
 template <class Base>
-void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     JSContextRef execRef = toRef(exec);
     JSObjectRef thisRef = toRef(this);
     
     for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) {
 {
     JSContextRef execRef = toRef(exec);
     JSObjectRef thisRef = toRef(this);
     
     for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) {
-            JSLock::DropAllLocks dropAllLocks(exec);
+            APICallbackShim callbackShim(exec);
             getPropertyNames(execRef, thisRef, toRef(&propertyNames));
         }
         
             getPropertyNames(execRef, thisRef, toRef(&propertyNames));
         }
         
@@ -390,7 +416,7 @@ void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray
             for (iterator it = staticValues->begin(); it != end; ++it) {
                 UString::Rep* name = it->first.get();
                 StaticValueEntry* entry = it->second;
             for (iterator it = staticValues->begin(); it != end; ++it) {
                 UString::Rep* name = it->first.get();
                 StaticValueEntry* entry = it->second;
-                if (entry->getProperty && !(entry->attributes & kJSPropertyAttributeDontEnum))
+                if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)))
                     propertyNames.add(Identifier(exec, name));
             }
         }
                     propertyNames.add(Identifier(exec, name));
             }
         }
@@ -401,13 +427,13 @@ void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray
             for (iterator it = staticFunctions->begin(); it != end; ++it) {
                 UString::Rep* name = it->first.get();
                 StaticFunctionEntry* entry = it->second;
             for (iterator it = staticFunctions->begin(); it != end; ++it) {
                 UString::Rep* name = it->first.get();
                 StaticFunctionEntry* entry = it->second;
-                if (!(entry->attributes & kJSPropertyAttributeDontEnum))
+                if (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))
                     propertyNames.add(Identifier(exec, name));
             }
         }
     }
     
                     propertyNames.add(Identifier(exec, name));
             }
         }
     }
     
-    Base::getPropertyNames(exec, propertyNames);
+    Base::getOwnPropertyNames(exec, propertyNames, mode);
 }
 
 template <class Base>
 }
 
 template <class Base>
@@ -426,7 +452,7 @@ double JSCallbackObject<Base>::toNumber(ExecState* exec) const
             JSValueRef exception = 0;
             JSValueRef value;
             {
             JSValueRef exception = 0;
             JSValueRef value;
             {
-                JSLock::DropAllLocks dropAllLocks(exec);
+                APICallbackShim callbackShim(exec);
                 value = convertToType(ctx, thisRef, kJSTypeNumber, &exception);
             }
             if (exception) {
                 value = convertToType(ctx, thisRef, kJSTypeNumber, &exception);
             }
             if (exception) {
@@ -435,7 +461,8 @@ double JSCallbackObject<Base>::toNumber(ExecState* exec) const
             }
 
             double dValue;
             }
 
             double dValue;
-            return toJS(exec, value).getNumber(dValue) ? dValue : NaN;
+            if (value)
+                return toJS(exec, value).getNumber(dValue) ? dValue : NaN;
         }
             
     return Base::toNumber(exec);
         }
             
     return Base::toNumber(exec);
@@ -452,14 +479,15 @@ UString JSCallbackObject<Base>::toString(ExecState* exec) const
             JSValueRef exception = 0;
             JSValueRef value;
             {
             JSValueRef exception = 0;
             JSValueRef value;
             {
-                JSLock::DropAllLocks dropAllLocks(exec);
+                APICallbackShim callbackShim(exec);
                 value = convertToType(ctx, thisRef, kJSTypeString, &exception);
             }
             if (exception) {
                 exec->setException(toJS(exec, exception));
                 return "";
             }
                 value = convertToType(ctx, thisRef, kJSTypeString, &exception);
             }
             if (exception) {
                 exec->setException(toJS(exec, exception));
                 return "";
             }
-            return toJS(exec, value).getString();
+            if (value)
+                return toJS(exec, value).getString(exec);
         }
             
     return Base::toString(exec);
         }
             
     return Base::toString(exec);
@@ -504,16 +532,17 @@ JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identif
                     JSValueRef exception = 0;
                     JSValueRef value;
                     {
                     JSValueRef exception = 0;
                     JSValueRef value;
                     {
-                        JSLock::DropAllLocks dropAllLocks(exec);
+                        APICallbackShim callbackShim(exec);
                         value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
                     }
                         value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
                     }
-                    exec->setException(toJS(exec, exception));
+                    if (exception) {
+                        exec->setException(toJS(exec, exception));
+                        return jsUndefined();
+                    }
                     if (value)
                         return toJS(exec, value);
                     if (value)
                         return toJS(exec, value);
-                    if (exception)
-                        return jsUndefined();
                 }
                 }
-                    
+
     return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback.");
 }
 
     return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback.");
 }
 
@@ -557,14 +586,15 @@ JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier
             JSValueRef exception = 0;
             JSValueRef value;
             {
             JSValueRef exception = 0;
             JSValueRef value;
             {
-                JSLock::DropAllLocks dropAllLocks(exec);
+                APICallbackShim callbackShim(exec);
                 value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
             }
                 value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
             }
-            exec->setException(toJS(exec, exception));
+            if (exception) {
+                exec->setException(toJS(exec, exception));
+                return jsUndefined();
+            }
             if (value)
                 return toJS(exec, value);
             if (value)
                 return toJS(exec, value);
-            if (exception)
-                return jsUndefined();
         }
             
     return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist.");
         }
             
     return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist.");
index afde7ce1a201efbdcd122e1aeed8537c0f0a52e9..d75d5cdbd499b3169a61c73e652e4c3a4304c2a5 100644 (file)
@@ -34,6 +34,7 @@
 #include <runtime/ObjectPrototype.h>
 #include <runtime/Identifier.h>
 
 #include <runtime/ObjectPrototype.h>
 #include <runtime/Identifier.h>
 
+using namespace std;
 using namespace JSC;
 
 const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 using namespace JSC;
 
 const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -52,7 +53,7 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass*
     , callAsConstructor(definition->callAsConstructor)
     , hasInstance(definition->hasInstance)
     , convertToType(definition->convertToType)
     , callAsConstructor(definition->callAsConstructor)
     , hasInstance(definition->hasInstance)
     , convertToType(definition->convertToType)
-    , m_className(UString::Rep::createFromUTF8(definition->className))
+    , m_className(UString::createFromUTF8(definition->className).rep()->ref())
     , m_staticValues(0)
     , m_staticFunctions(0)
 {
     , m_staticValues(0)
     , m_staticFunctions(0)
 {
@@ -61,8 +62,9 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass*
     if (const JSStaticValue* staticValue = definition->staticValues) {
         m_staticValues = new OpaqueJSClassStaticValuesTable();
         while (staticValue->name) {
     if (const JSStaticValue* staticValue = definition->staticValues) {
         m_staticValues = new OpaqueJSClassStaticValuesTable();
         while (staticValue->name) {
-            m_staticValues->add(UString::Rep::createFromUTF8(staticValue->name),
-                              new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes));
+            // Use a local variable here to sidestep an RVCT compiler bug.
+            StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes);
+            m_staticValues->add(UString::createFromUTF8(staticValue->name).rep()->ref(), entry);
             ++staticValue;
         }
     }
             ++staticValue;
         }
     }
@@ -70,8 +72,9 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass*
     if (const JSStaticFunction* staticFunction = definition->staticFunctions) {
         m_staticFunctions = new OpaqueJSClassStaticFunctionsTable();
         while (staticFunction->name) {
     if (const JSStaticFunction* staticFunction = definition->staticFunctions) {
         m_staticFunctions = new OpaqueJSClassStaticFunctionsTable();
         while (staticFunction->name) {
-            m_staticFunctions->add(UString::Rep::createFromUTF8(staticFunction->name),
-                                 new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes));
+            // Use a local variable here to sidestep an RVCT compiler bug.
+            StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes);
+            m_staticFunctions->add(UString::createFromUTF8(staticFunction->name).rep()->ref(), entry);
             ++staticFunction;
         }
     }
             ++staticFunction;
         }
     }
@@ -82,12 +85,12 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass*
 
 OpaqueJSClass::~OpaqueJSClass()
 {
 
 OpaqueJSClass::~OpaqueJSClass()
 {
-    ASSERT(!m_className.rep()->identifierTable());
+    ASSERT(!m_className.rep()->isIdentifier());
 
     if (m_staticValues) {
         OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end();
         for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) {
 
     if (m_staticValues) {
         OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end();
         for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) {
-            ASSERT(!it->first->identifierTable());
+            ASSERT(!it->first->isIdentifier());
             delete it->second;
         }
         delete m_staticValues;
             delete it->second;
         }
         delete m_staticValues;
@@ -96,7 +99,7 @@ OpaqueJSClass::~OpaqueJSClass()
     if (m_staticFunctions) {
         OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end();
         for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) {
     if (m_staticFunctions) {
         OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end();
         for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) {
-            ASSERT(!it->first->identifierTable());
+            ASSERT(!it->first->isIdentifier());
             delete it->second;
         }
         delete m_staticFunctions;
             delete it->second;
         }
         delete m_staticFunctions;
@@ -115,42 +118,35 @@ static void clearReferenceToPrototype(JSObjectRef prototype)
 {
     OpaqueJSClassContextData* jsClassData = static_cast<OpaqueJSClassContextData*>(JSObjectGetPrivate(prototype));
     ASSERT(jsClassData);
 {
     OpaqueJSClassContextData* jsClassData = static_cast<OpaqueJSClassContextData*>(JSObjectGetPrivate(prototype));
     ASSERT(jsClassData);
-    jsClassData->cachedPrototype = 0;
+    jsClassData->cachedPrototype.clear(toJS(prototype));
 }
 
 }
 
-PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* definition)
+PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* clientDefinition)
 {
 {
-    if (const JSStaticFunction* staticFunctions = definition->staticFunctions) {
-        // copy functions into a prototype class
-        JSClassDefinition protoDefinition = kJSClassDefinitionEmpty;
-        protoDefinition.staticFunctions = staticFunctions;
-        protoDefinition.finalize = clearReferenceToPrototype;
-        
-        // We are supposed to use JSClassRetain/Release but since we know that we currently have
-        // the only reference to this class object we cheat and use a RefPtr instead.
-        RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0));
-
-        // remove functions from the original class
-        JSClassDefinition objectDefinition = *definition;
-        objectDefinition.staticFunctions = 0;
-
-        return adoptRef(new OpaqueJSClass(&objectDefinition, protoClass.get()));
-    }
+    JSClassDefinition definition = *clientDefinition; // Avoid modifying client copy.
 
 
-    return adoptRef(new OpaqueJSClass(definition, 0));
+    JSClassDefinition protoDefinition = kJSClassDefinitionEmpty;
+    protoDefinition.finalize = clearReferenceToPrototype;
+    swap(definition.staticFunctions, protoDefinition.staticFunctions); // Move static functions to the prototype.
+    
+    // We are supposed to use JSClassRetain/Release but since we know that we currently have
+    // the only reference to this class object we cheat and use a RefPtr instead.
+    RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0));
+    return adoptRef(new OpaqueJSClass(&definition, protoClass.get()));
 }
 
 OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
     : m_class(jsClass)
 }
 
 OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
     : m_class(jsClass)
-    , cachedPrototype(0)
 {
     if (jsClass->m_staticValues) {
         staticValues = new OpaqueJSClassStaticValuesTable;
         OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end();
         for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) {
 {
     if (jsClass->m_staticValues) {
         staticValues = new OpaqueJSClassStaticValuesTable;
         OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end();
         for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) {
-            ASSERT(!it->first->identifierTable());
-            staticValues->add(UString::Rep::createCopying(it->first->data(), it->first->size()),
-                              new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes));
+            ASSERT(!it->first->isIdentifier());
+            // Use a local variable here to sidestep an RVCT compiler bug.
+            StaticValueEntry* entry = new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes);
+            staticValues->add(UString::Rep::create(it->first->data(), it->first->size()), entry);
+
         }
             
     } else
         }
             
     } else
@@ -161,9 +157,10 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
         staticFunctions = new OpaqueJSClassStaticFunctionsTable;
         OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end();
         for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) {
         staticFunctions = new OpaqueJSClassStaticFunctionsTable;
         OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end();
         for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) {
-            ASSERT(!it->first->identifierTable());
-            staticFunctions->add(UString::Rep::createCopying(it->first->data(), it->first->size()),
-                              new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes));
+            ASSERT(!it->first->isIdentifier());
+            // Use a local variable here to sidestep an RVCT compiler bug.
+            StaticFunctionEntry* entry = new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes);
+            staticFunctions->add(UString::Rep::create(it->first->data(), it->first->size()), entry);
         }
             
     } else
         }
             
     } else
@@ -240,5 +237,5 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec)
                 jsClassData.cachedPrototype->setPrototype(prototype);
         }
     }
                 jsClassData.cachedPrototype->setPrototype(prototype);
         }
     }
-    return jsClassData.cachedPrototype;
+    return jsClassData.cachedPrototype.get();
 }
 }
index 4f6761845441f3a6acc37fd918a3bc6fcf804b06..ae60aadef91baa47b8e345f7ed4fb8263834457b 100644 (file)
 #include <runtime/JSObject.h>
 #include <runtime/Protect.h>
 #include <runtime/UString.h>
 #include <runtime/JSObject.h>
 #include <runtime/Protect.h>
 #include <runtime/UString.h>
+#include <runtime/WeakGCPtr.h>
 #include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
 
 #include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
 
-struct StaticValueEntry {
+struct StaticValueEntry : FastAllocBase {
     StaticValueEntry(JSObjectGetPropertyCallback _getProperty, JSObjectSetPropertyCallback _setProperty, JSPropertyAttributes _attributes)
         : getProperty(_getProperty), setProperty(_setProperty), attributes(_attributes)
     {
     StaticValueEntry(JSObjectGetPropertyCallback _getProperty, JSObjectSetPropertyCallback _setProperty, JSPropertyAttributes _attributes)
         : getProperty(_getProperty), setProperty(_setProperty), attributes(_attributes)
     {
@@ -45,7 +46,7 @@ struct StaticValueEntry {
     JSPropertyAttributes attributes;
 };
 
     JSPropertyAttributes attributes;
 };
 
-struct StaticFunctionEntry {
+struct StaticFunctionEntry : FastAllocBase {
     StaticFunctionEntry(JSObjectCallAsFunctionCallback _callAsFunction, JSPropertyAttributes _attributes)
         : callAsFunction(_callAsFunction), attributes(_attributes)
     {
     StaticFunctionEntry(JSObjectCallAsFunctionCallback _callAsFunction, JSPropertyAttributes _attributes)
         : callAsFunction(_callAsFunction), attributes(_attributes)
     {
@@ -58,7 +59,7 @@ struct StaticFunctionEntry {
 typedef HashMap<RefPtr<JSC::UString::Rep>, StaticValueEntry*> OpaqueJSClassStaticValuesTable;
 typedef HashMap<RefPtr<JSC::UString::Rep>, StaticFunctionEntry*> OpaqueJSClassStaticFunctionsTable;
 
 typedef HashMap<RefPtr<JSC::UString::Rep>, StaticValueEntry*> OpaqueJSClassStaticValuesTable;
 typedef HashMap<RefPtr<JSC::UString::Rep>, StaticFunctionEntry*> OpaqueJSClassStaticFunctionsTable;
 
-class OpaqueJSClass;
+struct OpaqueJSClass;
 
 // An OpaqueJSClass (JSClass) is created without a context, so it can be used with any context, even across context groups.
 // This structure holds data members that vary across context groups.
 
 // An OpaqueJSClass (JSClass) is created without a context, so it can be used with any context, even across context groups.
 // This structure holds data members that vary across context groups.
@@ -76,7 +77,7 @@ struct OpaqueJSClassContextData : Noncopyable {
 
     OpaqueJSClassStaticValuesTable* staticValues;
     OpaqueJSClassStaticFunctionsTable* staticFunctions;
 
     OpaqueJSClassStaticValuesTable* staticValues;
     OpaqueJSClassStaticFunctionsTable* staticFunctions;
-    JSC::JSObject* cachedPrototype;
+    JSC::WeakGCPtr<JSC::JSObject> cachedPrototype;
 };
 
 struct OpaqueJSClass : public ThreadSafeShared<OpaqueJSClass> {
 };
 
 struct OpaqueJSClass : public ThreadSafeShared<OpaqueJSClass> {
index a3bdc69ab2f24f7a32bed6325992391bfe4db773..2c763387666f0f0127557edc2d62255ba093aaba 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "config.h"
 #include "JSContextRef.h"
 
 #include "config.h"
 #include "JSContextRef.h"
+#include "JSContextRefPrivate.h"
 
 #include "APICast.h"
 #include "InitializeThreading.h"
 
 #include "APICast.h"
 #include "InitializeThreading.h"
@@ -34,7 +35,7 @@
 #include "JSObject.h"
 #include <wtf/Platform.h>
 
 #include "JSObject.h"
 #include <wtf/Platform.h>
 
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 #include <mach-o/dyld.h>
 
 static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0
 #include <mach-o/dyld.h>
 
 static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0
@@ -45,7 +46,7 @@ using namespace JSC;
 JSContextGroupRef JSContextGroupCreate()
 {
     initializeThreading();
 JSContextGroupRef JSContextGroupCreate()
 {
     initializeThreading();
-    return toRef(JSGlobalData::create().releaseRef());
+    return toRef(JSGlobalData::createNonDefault().releaseRef());
 }
 
 JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group)
 }
 
 JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group)
@@ -62,7 +63,7 @@ void JSContextGroupRelease(JSContextGroupRef group)
 JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
 {
     initializeThreading();
 JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
 {
     initializeThreading();
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
     // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed
     // to use a unique JSGlobalData, we use a shared one for compatibility.
 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
     // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed
     // to use a unique JSGlobalData, we use a shared one for compatibility.
 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
@@ -70,10 +71,10 @@ JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
 #else
     {
 #endif
 #else
     {
 #endif
-        JSLock lock(true);
+        JSLock lock(LockForReal);
         return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass);
     }
         return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass);
     }
-#endif // PLATFORM(DARWIN)
+#endif // OS(DARWIN)
 
     return JSGlobalContextCreateInGroup(0, globalObjectClass);
 }
 
     return JSGlobalContextCreateInGroup(0, globalObjectClass);
 }
@@ -82,9 +83,10 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass
 {
     initializeThreading();
 
 {
     initializeThreading();
 
-    JSLock lock(true);
+    JSLock lock(LockForReal);
+    RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createNonDefault();
 
 
-    RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::create();
+    APIEntryShim entryShim(globalData.get(), false);
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
     globalData->makeUsableFromMultipleThreads();
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
     globalData->makeUsableFromMultipleThreads();
@@ -107,12 +109,9 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass
 JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
 {
     ExecState* exec = toJS(ctx);
 JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
 {
     ExecState* exec = toJS(ctx);
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSGlobalData& globalData = exec->globalData();
 
     JSGlobalData& globalData = exec->globalData();
-
-    globalData.heap.registerThread();
-
     gcProtect(exec->dynamicGlobalObject());
     globalData.ref();
     return ctx;
     gcProtect(exec->dynamicGlobalObject());
     globalData.ref();
     return ctx;
@@ -123,25 +122,26 @@ void JSGlobalContextRelease(JSGlobalContextRef ctx)
     ExecState* exec = toJS(ctx);
     JSLock lock(exec);
 
     ExecState* exec = toJS(ctx);
     JSLock lock(exec);
 
+    JSGlobalData& globalData = exec->globalData();
+    IdentifierTable* savedIdentifierTable = setCurrentIdentifierTable(globalData.identifierTable);
+
     gcUnprotect(exec->dynamicGlobalObject());
 
     gcUnprotect(exec->dynamicGlobalObject());
 
-    JSGlobalData& globalData = exec->globalData();
     if (globalData.refCount() == 2) { // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain().
         // The last reference was released, this is our last chance to collect.
     if (globalData.refCount() == 2) { // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain().
         // The last reference was released, this is our last chance to collect.
-        ASSERT(!globalData.heap.protectedObjectCount());
-        ASSERT(!globalData.heap.isBusy());
         globalData.heap.destroy();
     } else
         globalData.heap.destroy();
     } else
-        globalData.heap.collect();
+        globalData.heap.collectAllGarbage();
 
     globalData.deref();
 
     globalData.deref();
+
+    setCurrentIdentifierTable(savedIdentifierTable);
 }
 
 JSObjectRef JSContextGetGlobalObject(JSContextRef ctx)
 {
     ExecState* exec = toJS(ctx);
 }
 
 JSObjectRef JSContextGetGlobalObject(JSContextRef ctx)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
     return toRef(exec->lexicalGlobalObject()->toThisObject(exec));
 
     // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
     return toRef(exec->lexicalGlobalObject()->toThisObject(exec));
@@ -152,3 +152,11 @@ JSContextGroupRef JSContextGetGroup(JSContextRef ctx)
     ExecState* exec = toJS(ctx);
     return toRef(&exec->globalData());
 }
     ExecState* exec = toJS(ctx);
     return toRef(&exec->globalData());
 }
+
+JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx)
+{
+    ExecState* exec = toJS(ctx);
+    APIEntryShim entryShim(exec);
+
+    return toGlobalRef(exec->lexicalGlobalObject()->globalExec());
+}
diff --git a/API/JSContextRefPrivate.h b/API/JSContextRefPrivate.h
new file mode 100644 (file)
index 0000000..ff014ec
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this 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 JSContextRefPrivate_h
+#define JSContextRefPrivate_h
+
+#include <JavaScriptCore/JSObjectRef.h>
+#include <JavaScriptCore/JSValueRef.h>
+#include <JavaScriptCore/WebKitAvailability.h>
+
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+@function
+@abstract Gets the global context of a JavaScript execution context.
+@param ctx The JSContext whose global context you want to get.
+@result ctx's global context.
+*/
+JS_EXPORT JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JSContextRefPrivate_h */
index 50ee6354f9484a095d9830aee883a33f6d9bb55f..faaa4eb669753451ab997f20b40d81b8e55bde26 100644 (file)
@@ -28,6 +28,7 @@
 #include "JSObjectRef.h"
 
 #include "APICast.h"
 #include "JSObjectRef.h"
 
 #include "APICast.h"
+#include "CodeBlock.h"
 #include "DateConstructor.h"
 #include "ErrorConstructor.h"
 #include "FunctionConstructor.h"
 #include "DateConstructor.h"
 #include "ErrorConstructor.h"
 #include "FunctionConstructor.h"
@@ -75,8 +76,7 @@ void JSClassRelease(JSClassRef jsClass)
 JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
 {
     ExecState* exec = toJS(ctx);
 JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     if (!jsClass)
         return toRef(new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure())); // slightly more efficient
 
     if (!jsClass)
         return toRef(new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure())); // slightly more efficient
@@ -91,8 +91,7 @@ JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
 JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
 {
     ExecState* exec = toJS(ctx);
 JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
     
 
     Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
     
@@ -102,8 +101,7 @@ JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name,
 JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
 {
     ExecState* exec = toJS(ctx);
 JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsPrototype = jsClass ? jsClass->prototype(exec) : 0;
     if (!jsPrototype)
 
     JSValue jsPrototype = jsClass ? jsClass->prototype(exec) : 0;
     if (!jsPrototype)
@@ -117,8 +115,7 @@ JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObje
 JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
     
 
     Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
     
@@ -140,8 +137,7 @@ JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned pa
 JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* result;
     if (argumentCount) {
 
     JSObject* result;
     if (argumentCount) {
@@ -166,8 +162,7 @@ JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSVa
 JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     MarkedArgumentBuffer argList;
     for (size_t i = 0; i < argumentCount; ++i)
 
     MarkedArgumentBuffer argList;
     for (size_t i = 0; i < argumentCount; ++i)
@@ -187,8 +182,7 @@ JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSVal
 JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     MarkedArgumentBuffer argList;
     for (size_t i = 0; i < argumentCount; ++i)
 
     MarkedArgumentBuffer argList;
     for (size_t i = 0; i < argumentCount; ++i)
@@ -208,8 +202,7 @@ JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSVa
 JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     MarkedArgumentBuffer argList;
     for (size_t i = 0; i < argumentCount; ++i)
 
     MarkedArgumentBuffer argList;
     for (size_t i = 0; i < argumentCount; ++i)
@@ -229,8 +222,7 @@ JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSV
 JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object)
 {
     ExecState* exec = toJS(ctx);
 JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsObject = toJS(object);
     return toRef(exec, jsObject->prototype());
 
     JSObject* jsObject = toJS(object);
     return toRef(exec, jsObject->prototype());
@@ -239,8 +231,7 @@ JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object)
 void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
 void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsObject = toJS(object);
     JSValue jsValue = toJS(exec, value);
 
     JSObject* jsObject = toJS(object);
     JSValue jsValue = toJS(exec, value);
@@ -251,8 +242,7 @@ void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value
 bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
 {
     ExecState* exec = toJS(ctx);
 bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsObject = toJS(object);
     
 
     JSObject* jsObject = toJS(object);
     
@@ -262,8 +252,7 @@ bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef prope
 JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsObject = toJS(object);
 
 
     JSObject* jsObject = toJS(object);
 
@@ -279,8 +268,7 @@ JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef
 void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsObject = toJS(object);
     Identifier name(propertyName->identifier(&exec->globalData()));
 
     JSObject* jsObject = toJS(object);
     Identifier name(propertyName->identifier(&exec->globalData()));
@@ -303,8 +291,7 @@ void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef prope
 JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsObject = toJS(object);
 
 
     JSObject* jsObject = toJS(object);
 
@@ -321,8 +308,7 @@ JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsi
 void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsObject = toJS(object);
     JSValue jsValue = toJS(exec, value);
 
     JSObject* jsObject = toJS(object);
     JSValue jsValue = toJS(exec, value);
@@ -338,8 +324,7 @@ void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned p
 bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsObject = toJS(object);
 
 
     JSObject* jsObject = toJS(object);
 
@@ -388,8 +373,7 @@ bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
 JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsObject = toJS(object);
     JSObject* jsThisObject = toJS(thisObject);
 
     JSObject* jsObject = toJS(object);
     JSObject* jsThisObject = toJS(thisObject);
@@ -426,8 +410,7 @@ bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
 JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSObject* jsObject = toJS(object);
 
 
     JSObject* jsObject = toJS(object);
 
@@ -449,7 +432,7 @@ JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size
     return result;
 }
 
     return result;
 }
 
-struct OpaqueJSPropertyNameArray {
+struct OpaqueJSPropertyNameArray : FastAllocBase {
     OpaqueJSPropertyNameArray(JSGlobalData* globalData)
         : refCount(0)
         , globalData(globalData)
     OpaqueJSPropertyNameArray(JSGlobalData* globalData)
         : refCount(0)
         , globalData(globalData)
@@ -465,8 +448,7 @@ JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef o
 {
     JSObject* jsObject = toJS(object);
     ExecState* exec = toJS(ctx);
 {
     JSObject* jsObject = toJS(object);
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSGlobalData* globalData = &exec->globalData();
 
 
     JSGlobalData* globalData = &exec->globalData();
 
@@ -491,7 +473,7 @@ JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
 void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
 {
     if (--array->refCount == 0) {
 void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
 {
     if (--array->refCount == 0) {
-        JSLock lock(array->globalData->isSharedInstance);
+        APIEntryShim entryShim(array->globalData, false);
         delete array;
     }
 }
         delete array;
     }
 }
@@ -509,9 +491,6 @@ JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size
 void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
 {
     PropertyNameArray* propertyNames = toJS(array);
 void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
 {
     PropertyNameArray* propertyNames = toJS(array);
-
-    propertyNames->globalData()->heap.registerThread();
-    JSLock lock(propertyNames->globalData()->isSharedInstance);
-
+    APIEntryShim entryShim(propertyNames->globalData());
     propertyNames->add(propertyName->identifier(propertyNames->globalData()));
 }
     propertyNames->add(propertyName->identifier(propertyNames->globalData()));
 }
index 8b17ee2a7cdcc9faa9602ba2b0f282ddf0984817..c58b95821043474094fcc4fe7e9a1047b259d262 100644 (file)
@@ -37,7 +37,7 @@
 extern "C" {
 #endif
 
 extern "C" {
 #endif
 
-#if !defined(WIN32) && !defined(_WIN32)
+#if !defined(WIN32) && !defined(_WIN32) && !defined(__WINSCW__)
 /*!
 @typedef JSChar
 @abstract A Unicode character.
 /*!
 @typedef JSChar
 @abstract A Unicode character.
index 2207181bd6223e833533c1a2f2b4c4ac792c834f..a12cc3409a2e10dd5ef6c8986fe187e6bdf8276a 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <wtf/Platform.h>
 #include "APICast.h"
 
 #include <wtf/Platform.h>
 #include "APICast.h"
+#include "APIShims.h"
 #include "JSCallbackObject.h"
 
 #include <runtime/JSGlobalObject.h>
 #include "JSCallbackObject.h"
 
 #include <runtime/JSGlobalObject.h>
 
 #include <algorithm> // for std::min
 
 
 #include <algorithm> // for std::min
 
-JSType JSValueGetType(JSContextRef ctx, JSValueRef value)
+using namespace JSC;
+
+::JSType JSValueGetType(JSContextRef ctx, JSValueRef value)
 {
 {
-    JSC::ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSC::JSLock lock(exec);
+    ExecState* exec = toJS(ctx);
+    APIEntryShim entryShim(exec);
 
 
-    JSC::JSValue jsValue = toJS(exec, value);
+    JSValue jsValue = toJS(exec, value);
 
     if (jsValue.isUndefined())
         return kJSTypeUndefined;
 
     if (jsValue.isUndefined())
         return kJSTypeUndefined;
@@ -63,13 +65,10 @@ JSType JSValueGetType(JSContextRef ctx, JSValueRef value)
     return kJSTypeObject;
 }
 
     return kJSTypeObject;
 }
 
-using namespace JSC; // placed here to avoid conflict between JSC::JSType and JSType, above.
-
 bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
 bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isUndefined();
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isUndefined();
@@ -78,8 +77,7 @@ bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value)
 bool JSValueIsNull(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
 bool JSValueIsNull(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isNull();
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isNull();
@@ -88,8 +86,7 @@ bool JSValueIsNull(JSContextRef ctx, JSValueRef value)
 bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
 bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isBoolean();
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isBoolean();
@@ -98,8 +95,7 @@ bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value)
 bool JSValueIsNumber(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
 bool JSValueIsNumber(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isNumber();
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isNumber();
@@ -108,8 +104,7 @@ bool JSValueIsNumber(JSContextRef ctx, JSValueRef value)
 bool JSValueIsString(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
 bool JSValueIsString(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isString();
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isString();
@@ -118,8 +113,7 @@ bool JSValueIsString(JSContextRef ctx, JSValueRef value)
 bool JSValueIsObject(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
 bool JSValueIsObject(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isObject();
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.isObject();
@@ -128,8 +122,7 @@ bool JSValueIsObject(JSContextRef ctx, JSValueRef value)
 bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass)
 {
     ExecState* exec = toJS(ctx);
 bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     
 
     JSValue jsValue = toJS(exec, value);
     
@@ -145,8 +138,7 @@ bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsCla
 bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsA = toJS(exec, a);
     JSValue jsB = toJS(exec, b);
 
     JSValue jsA = toJS(exec, a);
     JSValue jsB = toJS(exec, b);
@@ -163,20 +155,18 @@ bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* ex
 bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b)
 {
     ExecState* exec = toJS(ctx);
 bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsA = toJS(exec, a);
     JSValue jsB = toJS(exec, b);
 
 
     JSValue jsA = toJS(exec, a);
     JSValue jsB = toJS(exec, b);
 
-    return JSValue::strictEqual(jsA, jsB);
+    return JSValue::strictEqual(exec, jsA, jsB);
 }
 
 bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 }
 
 bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
 
 
     JSValue jsValue = toJS(exec, value);
 
@@ -195,8 +185,7 @@ bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObject
 JSValueRef JSValueMakeUndefined(JSContextRef ctx)
 {
     ExecState* exec = toJS(ctx);
 JSValueRef JSValueMakeUndefined(JSContextRef ctx)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     return toRef(exec, jsUndefined());
 }
 
     return toRef(exec, jsUndefined());
 }
@@ -204,8 +193,7 @@ JSValueRef JSValueMakeUndefined(JSContextRef ctx)
 JSValueRef JSValueMakeNull(JSContextRef ctx)
 {
     ExecState* exec = toJS(ctx);
 JSValueRef JSValueMakeNull(JSContextRef ctx)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     return toRef(exec, jsNull());
 }
 
     return toRef(exec, jsNull());
 }
@@ -213,8 +201,7 @@ JSValueRef JSValueMakeNull(JSContextRef ctx)
 JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value)
 {
     ExecState* exec = toJS(ctx);
 JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     return toRef(exec, jsBoolean(value));
 }
 
     return toRef(exec, jsBoolean(value));
 }
@@ -222,8 +209,7 @@ JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value)
 JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
 {
     ExecState* exec = toJS(ctx);
 JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     return toRef(exec, jsNumber(exec, value));
 }
 
     return toRef(exec, jsNumber(exec, value));
 }
@@ -231,8 +217,7 @@ JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
 JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
 {
     ExecState* exec = toJS(ctx);
 JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     return toRef(exec, jsString(exec, string->ustring()));
 }
 
     return toRef(exec, jsString(exec, string->ustring()));
 }
@@ -240,8 +225,7 @@ JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
 bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
 bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.toBoolean(exec);
 
     JSValue jsValue = toJS(exec, value);
     return jsValue.toBoolean(exec);
@@ -250,8 +234,7 @@ bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
 double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
 
 
     JSValue jsValue = toJS(exec, value);
 
@@ -268,8 +251,7 @@ double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception
 JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     
 
     JSValue jsValue = toJS(exec, value);
     
@@ -286,8 +268,7 @@ JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef*
 JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
 JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
     JSValue jsValue = toJS(exec, value);
     
 
     JSValue jsValue = toJS(exec, value);
     
@@ -304,19 +285,17 @@ JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exce
 void JSValueProtect(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
 void JSValueProtect(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
 
-    JSValue jsValue = toJS(exec, value);
+    JSValue jsValue = toJSForGC(exec, value);
     gcProtect(jsValue);
 }
 
 void JSValueUnprotect(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
     gcProtect(jsValue);
 }
 
 void JSValueUnprotect(JSContextRef ctx, JSValueRef value)
 {
     ExecState* exec = toJS(ctx);
-    exec->globalData().heap.registerThread();
-    JSLock lock(exec);
+    APIEntryShim entryShim(exec);
 
 
-    JSValue jsValue = toJS(exec, value);
+    JSValue jsValue = toJSForGC(exec, value);
     gcUnprotect(jsValue);
 }
     gcUnprotect(jsValue);
 }
index 7c7b1af69f61c4c46348d4094095b37e2dd75066..f740abe3b135c36d24aaba853387b1ffdb825275 100644 (file)
@@ -42,7 +42,7 @@ PassRefPtr<OpaqueJSString> OpaqueJSString::create(const UString& ustring)
 UString OpaqueJSString::ustring() const
 {
     if (this && m_characters)
 UString OpaqueJSString::ustring() const
 {
     if (this && m_characters)
-        return UString(m_characters, m_length, true);
+        return UString(m_characters, m_length);
     return UString::null();
 }
 
     return UString::null();
 }
 
index 1f413e184365f76562bfbcb8fe4d406060a94f6e..ebc0cfb64d7d73afa086dbb546eacb5a9f156409 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "JavaScriptCore.h"
 #include "JSBasePrivate.h"
 
 #include "JavaScriptCore.h"
 #include "JSBasePrivate.h"
+#include "JSContextRefPrivate.h"
 #include <math.h>
 #define ASSERT_DISABLED 0
 #include <wtf/Assertions.h>
 #include <math.h>
 #define ASSERT_DISABLED 0
 #include <wtf/Assertions.h>
@@ -41,8 +42,8 @@ static double nan(const char*)
 
 #endif
 
 
 #endif
 
-static JSGlobalContextRef context = 0;
-static int failed = 0;
+static JSGlobalContextRef context;
+static int failed;
 static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
 {
     if (JSValueToBoolean(context, value) != expectedValue) {
 static void assertEqualsAsBoolean(JSValueRef value, bool expectedValue)
 {
     if (JSValueToBoolean(context, value) != expectedValue) {
@@ -165,6 +166,10 @@ static JSValueRef MyObject_getProperty(JSContextRef context, JSObjectRef object,
     if (JSStringIsEqualToUTF8CString(propertyName, "cantFind")) {
         return JSValueMakeUndefined(context);
     }
     if (JSStringIsEqualToUTF8CString(propertyName, "cantFind")) {
         return JSValueMakeUndefined(context);
     }
+    
+    if (JSStringIsEqualToUTF8CString(propertyName, "hasPropertyLie")) {
+        return 0;
+    }
 
     if (JSStringIsEqualToUTF8CString(propertyName, "throwOnGet")) {
         return JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
 
     if (JSStringIsEqualToUTF8CString(propertyName, "throwOnGet")) {
         return JSEvaluateScript(context, JSStringCreateWithUTF8CString("throw 'an exception'"), object, JSStringCreateWithUTF8CString("test script"), 1, exception);
@@ -175,7 +180,7 @@ static JSValueRef MyObject_getProperty(JSContextRef context, JSObjectRef object,
         return JSValueMakeNumber(context, 1);
     }
     
         return JSValueMakeNumber(context, 1);
     }
     
-    return NULL;
+    return JSValueMakeNull(context);
 }
 
 static bool MyObject_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
 }
 
 static bool MyObject_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
@@ -298,7 +303,7 @@ static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef objec
     }
 
     // string conversion -- forward to default object class
     }
 
     // string conversion -- forward to default object class
-    return NULL;
+    return JSValueMakeNull(context);
 }
 
 static JSStaticValue evilStaticValues[] = {
 }
 
 static JSStaticValue evilStaticValues[] = {
@@ -373,7 +378,7 @@ static JSValueRef EvilExceptionObject_convertToType(JSContextRef context, JSObje
         funcName = JSStringCreateWithUTF8CString("toStringExplicit");
         break;
     default:
         funcName = JSStringCreateWithUTF8CString("toStringExplicit");
         break;
     default:
-        return NULL;
+        return JSValueMakeNull(context);
         break;
     }
     
         break;
     }
     
@@ -381,7 +386,7 @@ static JSValueRef EvilExceptionObject_convertToType(JSContextRef context, JSObje
     JSStringRelease(funcName);    
     JSObjectRef function = JSValueToObject(context, func, exception);
     if (!function)
     JSStringRelease(funcName);    
     JSObjectRef function = JSValueToObject(context, func, exception);
     if (!function)
-        return NULL;
+        return JSValueMakeNull(context);
     JSValueRef value = JSObjectCallAsFunction(context, function, object, 0, NULL, exception);
     if (!value) {
         JSStringRef errorString = JSStringCreateWithUTF8CString("convertToType failed"); 
     JSValueRef value = JSObjectCallAsFunction(context, function, object, 0, NULL, exception);
     if (!value) {
         JSStringRef errorString = JSStringCreateWithUTF8CString("convertToType failed"); 
@@ -618,14 +623,27 @@ static JSClassRef Derived_class(JSContextRef context)
     return jsClass;
 }
 
     return jsClass;
 }
 
-static JSValueRef print_callAsFunction(JSContextRef context, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+static JSClassRef Derived2_class(JSContextRef context)
+{
+    static JSClassRef jsClass;
+    if (!jsClass) {
+        JSClassDefinition definition = kJSClassDefinitionEmpty;
+        definition.parentClass = Derived_class(context);
+        jsClass = JSClassCreate(&definition);
+    }
+    return jsClass;
+}
+
+static JSValueRef print_callAsFunction(JSContextRef ctx, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     UNUSED_PARAM(functionObject);
     UNUSED_PARAM(thisObject);
     UNUSED_PARAM(exception);
 {
     UNUSED_PARAM(functionObject);
     UNUSED_PARAM(thisObject);
     UNUSED_PARAM(exception);
+
+    ASSERT(JSContextGetGlobalContext(ctx) == context);
     
     if (argumentCount > 0) {
     
     if (argumentCount > 0) {
-        JSStringRef string = JSValueToStringCopy(context, arguments[0], NULL);
+        JSStringRef string = JSValueToStringCopy(ctx, arguments[0], NULL);
         size_t sizeUTF8 = JSStringGetMaximumUTF8CStringSize(string);
         char* stringUTF8 = (char*)malloc(sizeUTF8);
         JSStringGetUTF8CString(string, stringUTF8, sizeUTF8);
         size_t sizeUTF8 = JSStringGetMaximumUTF8CStringSize(string);
         char* stringUTF8 = (char*)malloc(sizeUTF8);
         JSStringGetUTF8CString(string, stringUTF8, sizeUTF8);
@@ -634,7 +652,7 @@ static JSValueRef print_callAsFunction(JSContextRef context, JSObjectRef functio
         JSStringRelease(string);
     }
     
         JSStringRelease(string);
     }
     
-    return JSValueMakeUndefined(context);
+    return JSValueMakeUndefined(ctx);
 }
 
 static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 }
 
 static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
@@ -734,6 +752,15 @@ static void testInitializeFinalize()
     ASSERT(JSObjectGetPrivate(o) == (void*)3);
 }
 
     ASSERT(JSObjectGetPrivate(o) == (void*)3);
 }
 
+static JSValueRef jsNumberValue =  NULL;
+
+static void makeGlobalNumberValue(JSContextRef context) {
+    JSValueRef v = JSValueMakeNumber(context, 420);
+    JSValueProtect(context, v);
+    jsNumberValue = v;
+    v = NULL;
+}
+
 int main(int argc, char* argv[])
 {
     const char *scriptPath = "testapi.js";
 int main(int argc, char* argv[])
 {
     const char *scriptPath = "testapi.js";
@@ -760,6 +787,7 @@ int main(int argc, char* argv[])
 
     JSGlobalContextRetain(context);
     JSGlobalContextRelease(context);
 
     JSGlobalContextRetain(context);
     JSGlobalContextRelease(context);
+    ASSERT(JSContextGetGlobalContext(context) == context);
     
     JSReportExtraMemoryCost(context, 0);
     JSReportExtraMemoryCost(context, 1);
     
     JSReportExtraMemoryCost(context, 0);
     JSReportExtraMemoryCost(context, 1);
@@ -944,10 +972,12 @@ int main(int argc, char* argv[])
     CFRelease(cfEmptyString);
     
     jsGlobalValue = JSObjectMake(context, NULL, NULL);
     CFRelease(cfEmptyString);
     
     jsGlobalValue = JSObjectMake(context, NULL, NULL);
+    makeGlobalNumberValue(context);
     JSValueProtect(context, jsGlobalValue);
     JSGarbageCollect(context);
     ASSERT(JSValueIsObject(context, jsGlobalValue));
     JSValueUnprotect(context, jsGlobalValue);
     JSValueProtect(context, jsGlobalValue);
     JSGarbageCollect(context);
     ASSERT(JSValueIsObject(context, jsGlobalValue));
     JSValueUnprotect(context, jsGlobalValue);
+    JSValueUnprotect(context, jsNumberValue);
 
     JSStringRef goodSyntax = JSStringCreateWithUTF8CString("x = 1;");
     JSStringRef badSyntax = JSStringCreateWithUTF8CString("x := 1;");
 
     JSStringRef goodSyntax = JSStringCreateWithUTF8CString("x = 1;");
     JSStringRef badSyntax = JSStringCreateWithUTF8CString("x := 1;");
@@ -1051,11 +1081,21 @@ int main(int argc, char* argv[])
     ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1));
     ASSERT(!JSObjectGetPrivate(myConstructor));
     
     ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1));
     ASSERT(!JSObjectGetPrivate(myConstructor));
     
+    string = JSStringCreateWithUTF8CString("Base");
+    JSObjectRef baseConstructor = JSObjectMakeConstructor(context, Base_class(context), NULL);
+    JSObjectSetProperty(context, globalObject, string, baseConstructor, kJSPropertyAttributeNone, NULL);
+    JSStringRelease(string);
+    
     string = JSStringCreateWithUTF8CString("Derived");
     JSObjectRef derivedConstructor = JSObjectMakeConstructor(context, Derived_class(context), NULL);
     JSObjectSetProperty(context, globalObject, string, derivedConstructor, kJSPropertyAttributeNone, NULL);
     JSStringRelease(string);
     
     string = JSStringCreateWithUTF8CString("Derived");
     JSObjectRef derivedConstructor = JSObjectMakeConstructor(context, Derived_class(context), NULL);
     JSObjectSetProperty(context, globalObject, string, derivedConstructor, kJSPropertyAttributeNone, NULL);
     JSStringRelease(string);
     
+    string = JSStringCreateWithUTF8CString("Derived2");
+    JSObjectRef derived2Constructor = JSObjectMakeConstructor(context, Derived2_class(context), NULL);
+    JSObjectSetProperty(context, globalObject, string, derived2Constructor, kJSPropertyAttributeNone, NULL);
+    JSStringRelease(string);
+
     o = JSObjectMake(context, NULL, NULL);
     JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeNone, NULL);
     JSObjectSetProperty(context, o, jsCFIString,  JSValueMakeNumber(context, 1), kJSPropertyAttributeDontEnum, NULL);
     o = JSObjectMake(context, NULL, NULL);
     JSObjectSetProperty(context, o, jsOneIString, JSValueMakeNumber(context, 1), kJSPropertyAttributeNone, NULL);
     JSObjectSetProperty(context, o, jsCFIString,  JSValueMakeNumber(context, 1), kJSPropertyAttributeDontEnum, NULL);
@@ -1154,7 +1194,7 @@ int main(int argc, char* argv[])
     } else {
         script = JSStringCreateWithUTF8CString(scriptUTF8);
         result = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
     } else {
         script = JSStringCreateWithUTF8CString(scriptUTF8);
         result = JSEvaluateScript(context, script, NULL, NULL, 1, &exception);
-        if (JSValueIsUndefined(context, result))
+        if (result && JSValueIsUndefined(context, result))
             printf("PASS: Test script executed successfully.\n");
         else {
             printf("FAIL: Test script returned unexpected value:\n");
             printf("PASS: Test script executed successfully.\n");
         else {
             printf("FAIL: Test script returned unexpected value:\n");
index 82756b57c6e3cc1353adcc0c31fa5e8b2476f05b..15c9e50db22e7da230f2bb895bd017bb38912bde 100644 (file)
@@ -113,6 +113,35 @@ if (foundRegularType)
 else
     fail("MyObject.regularType was not enumerated");
 
 else
     fail("MyObject.regularType was not enumerated");
 
+var alwaysOneDescriptor = Object.getOwnPropertyDescriptor(MyObject, "alwaysOne");
+shouldBe('typeof alwaysOneDescriptor', "object");
+shouldBe('alwaysOneDescriptor.value', MyObject.alwaysOne);
+shouldBe('alwaysOneDescriptor.configurable', true);
+shouldBe('alwaysOneDescriptor.enumerable', false); // Actually it is.
+var cantFindDescriptor = Object.getOwnPropertyDescriptor(MyObject, "cantFind");
+shouldBe('typeof cantFindDescriptor', "object");
+shouldBe('cantFindDescriptor.value', MyObject.cantFind);
+shouldBe('cantFindDescriptor.configurable', true);
+shouldBe('cantFindDescriptor.enumerable', false);
+try {
+    // If getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
+    Object.getOwnPropertyDescriptor(MyObject, "throwOnGet");
+} catch (e) {
+    pass("getting property descriptor of throwOnGet threw exception");
+}
+var myPropertyNameDescriptor = Object.getOwnPropertyDescriptor(MyObject, "myPropertyName");
+shouldBe('typeof myPropertyNameDescriptor', "object");
+shouldBe('myPropertyNameDescriptor.value', MyObject.myPropertyName);
+shouldBe('myPropertyNameDescriptor.configurable', true);
+shouldBe('myPropertyNameDescriptor.enumerable', false); // Actually it is.
+try {
+    // if getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
+    Object.getOwnPropertyDescriptor(MyObject, "hasPropertyLie");
+} catch (e) {
+    pass("getting property descriptor of hasPropertyLie threw exception");
+}
+shouldBe('Object.getOwnPropertyDescriptor(MyObject, "doesNotExist")', undefined);
+
 myObject = new MyObject();
 
 shouldBe("delete MyObject.regularType", true);
 myObject = new MyObject();
 
 shouldBe("delete MyObject.regularType", true);
@@ -140,6 +169,9 @@ shouldThrow("MyObject.hasPropertyLie");
 
 derived = new Derived();
 
 
 derived = new Derived();
 
+shouldBe("derived instanceof Derived", true);
+shouldBe("derived instanceof Base", true);
+
 // base properties and functions return 1 when called/gotten; derived, 2
 shouldBe("derived.baseProtoDup()", 2);
 shouldBe("derived.baseProto()", 1);
 // base properties and functions return 1 when called/gotten; derived, 2
 shouldBe("derived.baseProtoDup()", 2);
 shouldBe("derived.baseProto()", 1);
@@ -155,6 +187,51 @@ shouldBe("derived.baseOnly = 0", 1);
 shouldBe("derived.derivedOnly = 0", 2)
 shouldBe("derived.protoDup = 0", 2);
 
 shouldBe("derived.derivedOnly = 0", 2)
 shouldBe("derived.protoDup = 0", 2);
 
+derived2 = new Derived2();
+
+shouldBe("derived2 instanceof Derived2", true);
+shouldBe("derived2 instanceof Derived", true);
+shouldBe("derived2 instanceof Base", true);
+
+// base properties and functions return 1 when called/gotten; derived, 2
+shouldBe("derived2.baseProtoDup()", 2);
+shouldBe("derived2.baseProto()", 1);
+shouldBe("derived2.baseDup", 2);
+shouldBe("derived2.baseOnly", 1);
+shouldBe("derived2.protoOnly()", 2);
+shouldBe("derived2.protoDup", 2);
+shouldBe("derived2.derivedOnly", 2)
+
+// base properties throw 1 when set; derived, 2
+shouldBe("derived2.baseDup = 0", 2);
+shouldBe("derived2.baseOnly = 0", 1);
+shouldBe("derived2.derivedOnly = 0", 2)
+shouldBe("derived2.protoDup = 0", 2);
+
+shouldBe('Object.getOwnPropertyDescriptor(derived, "baseProto")', undefined);
+shouldBe('Object.getOwnPropertyDescriptor(derived, "baseProtoDup")', undefined);
+var baseDupDescriptor = Object.getOwnPropertyDescriptor(derived, "baseDup");
+shouldBe('typeof baseDupDescriptor', "object");
+shouldBe('baseDupDescriptor.value', derived.baseDup);
+shouldBe('baseDupDescriptor.configurable', true);
+shouldBe('baseDupDescriptor.enumerable', false);
+var baseOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "baseOnly");
+shouldBe('typeof baseOnlyDescriptor', "object");
+shouldBe('baseOnlyDescriptor.value', derived.baseOnly);
+shouldBe('baseOnlyDescriptor.configurable', true);
+shouldBe('baseOnlyDescriptor.enumerable', false);
+shouldBe('Object.getOwnPropertyDescriptor(derived, "protoOnly")', undefined);
+var protoDupDescriptor = Object.getOwnPropertyDescriptor(derived, "protoDup");
+shouldBe('typeof protoDupDescriptor', "object");
+shouldBe('protoDupDescriptor.value', derived.protoDup);
+shouldBe('protoDupDescriptor.configurable', true);
+shouldBe('protoDupDescriptor.enumerable', false);
+var derivedOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "derivedOnly");
+shouldBe('typeof derivedOnlyDescriptor', "object");
+shouldBe('derivedOnlyDescriptor.value', derived.derivedOnly);
+shouldBe('derivedOnlyDescriptor.configurable', true);
+shouldBe('derivedOnlyDescriptor.enumerable', false);
+
 shouldBe("undefined instanceof MyObject", false);
 EvilExceptionObject.hasInstance = function f() { return f(); };
 EvilExceptionObject.__proto__ = undefined;
 shouldBe("undefined instanceof MyObject", false);
 EvilExceptionObject.hasInstance = function f() { return f(); };
 EvilExceptionObject.__proto__ = undefined;
index 7b67dbe946e1f77829f2d853443642082b742e73..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,106 +0,0 @@
-/*
- *  Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-// This file exists to help compile the essential code of
-// JavaScriptCore all as one file, for compilers and build systems
-// that see a significant speed gain from this.
-
-#define KDE_USE_FINAL 1
-#define JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE 1
-#include "config.h"
-
-// these headers are included here to avoid confusion between ::JSType and JSC::JSType
-#include "JSCallbackConstructor.h"
-#include "JSCallbackFunction.h"
-#include "JSCallbackObject.h"
-
-#include "runtime/JSStaticScopeObject.cpp"
-#include "runtime/JSFunction.cpp"
-#include "runtime/Arguments.cpp"
-#include "runtime/JSAPIValueWrapper.cpp"
-#include "runtime/JSGlobalObjectFunctions.cpp"
-#include "runtime/PrototypeFunction.cpp"
-#include "runtime/GlobalEvalFunction.cpp"
-#include "debugger/Debugger.cpp"
-#include "runtime/JSArray.cpp"
-#include "runtime/ArrayConstructor.cpp"
-#include "runtime/ArrayPrototype.cpp"
-#include "runtime/BooleanConstructor.cpp"
-#include "runtime/BooleanObject.cpp"
-#include "runtime/BooleanPrototype.cpp"
-#include "runtime/Collector.cpp"
-#include "runtime/CommonIdentifiers.cpp"
-#include "runtime/DateConstructor.cpp"
-#include "runtime/DateConversion.cpp"
-#include "runtime/DatePrototype.cpp"
-#include "runtime/DateInstance.cpp"
-#include "wtf/dtoa.cpp"
-#include "runtime/ErrorInstance.cpp"
-#include "runtime/ErrorPrototype.cpp"
-#include "runtime/ErrorConstructor.cpp"
-#include "runtime/FunctionConstructor.cpp"
-#include "runtime/FunctionPrototype.cpp"
-#include "Grammar.cpp"
-#include "runtime/Identifier.cpp"
-#include "runtime/JSString.cpp"
-#include "runtime/JSNumberCell.cpp"
-#include "runtime/GetterSetter.cpp"
-#include "runtime/InternalFunction.cpp"
-#include "runtime/Completion.cpp"
-#include "runtime/JSImmediate.cpp"
-#include "runtime/JSLock.cpp"
-#include "runtime/JSWrapperObject.cpp"
-#include "parser/Lexer.cpp"
-#include "runtime/ArgList.cpp"
-#include "runtime/Lookup.cpp"
-#include "runtime/MathObject.cpp"
-#include "runtime/NativeErrorConstructor.cpp"
-#include "runtime/NativeErrorPrototype.cpp"
-#include "runtime/NumberConstructor.cpp"
-#include "runtime/NumberObject.cpp"
-#include "runtime/NumberPrototype.cpp"
-#include "parser/Nodes.cpp"
-#include "runtime/JSObject.cpp"
-#include "runtime/Error.cpp"
-#include "runtime/JSGlobalObject.cpp"
-#include "runtime/ObjectConstructor.cpp"
-#include "runtime/ObjectPrototype.cpp"
-#include "runtime/Operations.cpp"
-#include "parser/Parser.cpp"
-#include "runtime/PropertySlot.cpp"
-#include "runtime/PropertyNameArray.cpp"
-#include "runtime/RegExp.cpp"
-#include "runtime/RegExpConstructor.cpp"
-#include "runtime/RegExpObject.cpp"
-#include "runtime/RegExpPrototype.cpp"
-#include "runtime/ScopeChain.cpp"
-#include "runtime/StringConstructor.cpp"
-#include "runtime/StringObject.cpp"
-#include "runtime/StringPrototype.cpp"
-#include "runtime/UString.cpp"
-#include "runtime/JSValue.cpp"
-#include "runtime/CallData.cpp"
-#include "runtime/ConstructData.cpp"
-#include "runtime/JSCell.cpp"
-#include "runtime/JSVariableObject.cpp"
-#include "wtf/FastMalloc.cpp"
-#include "wtf/TCSystemAlloc.cpp"
-#include "bytecompiler/BytecodeGenerator.cpp"
-#include "interpreter/RegisterFile.cpp"
diff --git a/Android.mk b/Android.mk
new file mode 100644 (file)
index 0000000..e76da32
--- /dev/null
@@ -0,0 +1,216 @@
+##
+## Copyright 2009, The Android Open Source Project
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+##  * Redistributions of source code must retain the above copyright
+##    notice, this list of conditions and the following disclaimer.
+##  * Redistributions in binary form must reproduce the above copyright
+##    notice, this list of conditions and the following disclaimer in the
+##    documentation and/or other materials provided with the distribution.
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+##
+
+LOCAL_SRC_FILES := \
+       API/JSValueRef.cpp \
+       API/JSCallbackObject.cpp \
+       API/OpaqueJSString.cpp \
+       \
+       bytecode/CodeBlock.cpp \
+       bytecode/JumpTable.cpp \
+       bytecode/Opcode.cpp \
+       bytecode/SamplingTool.cpp \
+       bytecode/StructureStubInfo.cpp \
+       \
+       bytecompiler/BytecodeGenerator.cpp \
+       bytecompiler/NodesCodegen.cpp \
+       \
+       debugger/Debugger.cpp \
+       debugger/DebuggerActivation.cpp \
+       debugger/DebuggerCallFrame.cpp \
+       \
+       interpreter/CallFrame.cpp \
+       interpreter/Interpreter.cpp \
+       interpreter/RegisterFile.cpp \
+       \
+       parser/Lexer.cpp \
+       parser/Nodes.cpp \
+       parser/Parser.cpp \
+       parser/ParserArena.cpp \
+       \
+       pcre/pcre_compile.cpp \
+       pcre/pcre_exec.cpp \
+       pcre/pcre_tables.cpp \
+       pcre/pcre_ucp_searchfuncs.cpp \
+       pcre/pcre_xclass.cpp \
+       \
+       profiler/Profile.cpp \
+       profiler/ProfileGenerator.cpp \
+       profiler/ProfileNode.cpp \
+       profiler/Profiler.cpp \
+       \
+       runtime/ArgList.cpp \
+       runtime/Arguments.cpp \
+       runtime/ArrayConstructor.cpp \
+       runtime/ArrayPrototype.cpp \
+       runtime/BooleanConstructor.cpp \
+       runtime/BooleanObject.cpp \
+       runtime/BooleanPrototype.cpp \
+       runtime/CallData.cpp \
+       runtime/Collector.cpp \
+       runtime/CommonIdentifiers.cpp \
+       runtime/Completion.cpp \
+       runtime/ConstructData.cpp \
+       runtime/DateConstructor.cpp \
+       runtime/DateConversion.cpp \
+       runtime/DateInstance.cpp \
+       runtime/DatePrototype.cpp \
+       runtime/Error.cpp \
+       runtime/ErrorConstructor.cpp \
+       runtime/ErrorInstance.cpp \
+       runtime/ErrorPrototype.cpp \
+       runtime/ExceptionHelpers.cpp \
+       runtime/Executable.cpp \
+       runtime/FunctionConstructor.cpp \
+       runtime/FunctionPrototype.cpp \
+       runtime/GetterSetter.cpp \
+       runtime/GlobalEvalFunction.cpp \
+       runtime/Identifier.cpp \
+       runtime/InitializeThreading.cpp \
+       runtime/InternalFunction.cpp \
+       runtime/JSAPIValueWrapper.cpp \
+       runtime/JSActivation.cpp \
+       runtime/JSArray.cpp \
+       runtime/JSByteArray.cpp \
+       runtime/JSCell.cpp \
+       runtime/JSFunction.cpp \
+       runtime/JSGlobalData.cpp \
+       runtime/JSGlobalObject.cpp \
+       runtime/JSGlobalObjectFunctions.cpp \
+       runtime/JSImmediate.cpp \
+       runtime/JSLock.cpp \
+       runtime/JSNotAnObject.cpp \
+       runtime/JSNumberCell.cpp \
+       runtime/JSONObject.cpp \
+       runtime/JSObject.cpp \
+       runtime/JSPropertyNameIterator.cpp \
+       runtime/JSStaticScopeObject.cpp \
+       runtime/JSString.cpp \
+       runtime/JSValue.cpp \
+       runtime/JSVariableObject.cpp \
+       runtime/JSWrapperObject.cpp \
+       runtime/LiteralParser.cpp \
+       runtime/Lookup.cpp \
+       runtime/MarkStack.cpp \
+       runtime/MarkStackPosix.cpp \
+       runtime/MathObject.cpp \
+       runtime/NativeErrorConstructor.cpp \
+       runtime/NativeErrorPrototype.cpp \
+       runtime/NumberConstructor.cpp \
+       runtime/NumberObject.cpp \
+       runtime/NumberPrototype.cpp \
+       runtime/ObjectConstructor.cpp \
+       runtime/ObjectPrototype.cpp \
+       runtime/Operations.cpp \
+       runtime/PropertyDescriptor.cpp \
+       runtime/PropertyNameArray.cpp \
+       runtime/PropertySlot.cpp \
+       runtime/PrototypeFunction.cpp \
+       runtime/RegExp.cpp \
+       runtime/RegExpConstructor.cpp \
+       runtime/RegExpObject.cpp \
+       runtime/RegExpPrototype.cpp \
+       runtime/ScopeChain.cpp \
+       runtime/SmallStrings.cpp \
+       runtime/StringConstructor.cpp \
+       runtime/StringObject.cpp \
+       runtime/StringPrototype.cpp \
+       runtime/Structure.cpp \
+       runtime/StructureChain.cpp \
+       runtime/TimeoutChecker.cpp \
+       runtime/UString.cpp \
+       \
+       wrec/CharacterClass.cpp \
+       wrec/CharacterClassConstructor.cpp \
+       wrec/WREC.cpp \
+       wrec/WRECFunctors.cpp \
+       wrec/WRECGenerator.cpp \
+       wrec/WRECParser.cpp \
+       \
+       wtf/Assertions.cpp \
+       wtf/ByteArray.cpp \
+       wtf/CurrentTime.cpp \
+       wtf/DateMath.cpp \
+       wtf/FastMalloc.cpp \
+       wtf/HashTable.cpp \
+       wtf/MainThread.cpp \
+       wtf/RandomNumber.cpp \
+       wtf/RefCountedLeakCounter.cpp \
+       wtf/TCSystemAlloc.cpp \
+       wtf/ThreadIdentifierDataPthreads.cpp \
+       wtf/Threading.cpp \
+       wtf/ThreadingPthreads.cpp \
+       \
+       wtf/TypeTraits.cpp \
+       wtf/dtoa.cpp \
+       \
+       wtf/android/MainThreadAndroid.cpp \
+       \
+       wtf/unicode/CollatorDefault.cpp \
+       wtf/unicode/UTF8.cpp \
+       \
+       wtf/unicode/icu/CollatorICU.cpp
+
+# Rule to build grammar.y with our custom bison.
+GEN := $(intermediates)/parser/Grammar.cpp
+$(GEN) : PRIVATE_YACCFLAGS := -p jscyy
+$(GEN) : $(LOCAL_PATH)/parser/Grammar.y
+       $(call local-transform-y-to-cpp,.cpp)
+$(GEN) : $(LOCAL_BISON)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+# generated headers
+JSC_OBJECTS := $(addprefix $(intermediates)/runtime/, \
+                               ArrayPrototype.lut.h \
+                               DatePrototype.lut.h \
+                               JSONObject.lut.h \
+                               MathObject.lut.h \
+                               NumberConstructor.lut.h \
+                               RegExpConstructor.lut.h \
+                               RegExpObject.lut.h \
+                               StringPrototype.lut.h \
+                       )
+$(JSC_OBJECTS): PRIVATE_PATH := $(LOCAL_PATH)
+$(JSC_OBJECTS): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/create_hash_table $< -i > $@
+$(JSC_OBJECTS): $(LOCAL_PATH)/create_hash_table
+$(JSC_OBJECTS): $(intermediates)/%.lut.h : $(LOCAL_PATH)/%.cpp
+       $(transform-generated-source)
+
+
+LEXER_HEADER := $(intermediates)/Lexer.lut.h
+$(LEXER_HEADER): PRIVATE_PATH := $(LOCAL_PATH)
+$(LEXER_HEADER): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/create_hash_table $< -i > $@
+$(LEXER_HEADER): $(LOCAL_PATH)/create_hash_table
+$(LEXER_HEADER): $(intermediates)/%.lut.h : $(LOCAL_PATH)/parser/Keywords.table
+       $(transform-generated-source)
+
+CHARTABLES := $(intermediates)/chartables.c
+$(CHARTABLES): PRIVATE_PATH := $(LOCAL_PATH)
+$(CHARTABLES): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/pcre/dftables $@
+$(CHARTABLES): $(LOCAL_PATH)/pcre/dftables
+$(CHARTABLES): $(LOCAL_PATH)/pcre/pcre_internal.h
+       $(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES += $(JSC_OBJECTS) $(LEXER_HEADER) $(CHARTABLES)
diff --git a/Android.v8.wtf.mk b/Android.v8.wtf.mk
new file mode 100644 (file)
index 0000000..69128d6
--- /dev/null
@@ -0,0 +1,69 @@
+##
+## Copyright 2009, The Android Open Source Project
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+##  * Redistributions of source code must retain the above copyright
+##    notice, this list of conditions and the following disclaimer.
+##  * Redistributions in binary form must reproduce the above copyright
+##    notice, this list of conditions and the following disclaimer in the
+##    documentation and/or other materials provided with the distribution.
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+##
+
+# wtf source files
+
+LOCAL_SRC_FILES := \
+       pcre/pcre_compile.cpp \
+       pcre/pcre_exec.cpp \
+       pcre/pcre_tables.cpp \
+       pcre/pcre_ucp_searchfuncs.cpp \
+       pcre/pcre_xclass.cpp \
+       \
+       wtf/Assertions.cpp \
+       wtf/ByteArray.cpp \
+       wtf/CurrentTime.cpp \
+       wtf/DateMath.cpp \
+       wtf/FastMalloc.cpp \
+       wtf/HashTable.cpp \
+       wtf/MainThread.cpp \
+       wtf/RandomNumber.cpp \
+       wtf/RefCountedLeakCounter.cpp \
+       wtf/TCSystemAlloc.cpp \
+       wtf/ThreadIdentifierDataPthreads.cpp \
+       wtf/Threading.cpp \
+       wtf/ThreadingPthreads.cpp \
+       \
+       wtf/android/MainThreadAndroid.cpp \
+       \
+       wtf/TypeTraits.cpp \
+       wtf/dtoa.cpp \
+       \
+       wtf/unicode/CollatorDefault.cpp \
+       wtf/unicode/UTF8.cpp \
+       \
+       wtf/unicode/icu/CollatorICU.cpp
+
+CHARTABLES := $(intermediates)/chartables.c
+$(CHARTABLES): PRIVATE_PATH := $(LOCAL_PATH)
+$(CHARTABLES): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/pcre/dftables $@
+$(CHARTABLES): $(LOCAL_PATH)/pcre/dftables
+$(CHARTABLES): $(LOCAL_PATH)/pcre/pcre_internal.h
+       $(transform-generated-source)
+
+$(intermediates)/pcre/pcre_tables.o : $(CHARTABLES)
+
+# We do not add $(CHARTABLES) to LOCAL_GENERATED_SOURCES because the chartables.c file
+# is explicitly #included in pcre_tables.cpp.
diff --git a/DerivedSources.pro b/DerivedSources.pro
new file mode 100644 (file)
index 0000000..bd9f6ab
--- /dev/null
@@ -0,0 +1,95 @@
+# DerivedSources - qmake build info
+
+CONFIG -= debug_and_release
+
+TEMPLATE = lib
+TARGET = dummy
+
+QMAKE_EXTRA_TARGETS += generated_files
+
+CONFIG(standalone_package) {
+    isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$PWD/generated
+} else {
+    isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = generated
+}
+
+LUT_FILES += \
+    runtime/ArrayPrototype.cpp \
+    runtime/DatePrototype.cpp \
+    runtime/JSONObject.cpp \
+    runtime/MathObject.cpp \
+    runtime/NumberConstructor.cpp \
+    runtime/RegExpConstructor.cpp \
+    runtime/RegExpObject.cpp \
+    runtime/StringPrototype.cpp
+
+KEYWORDLUT_FILES += \
+    parser/Keywords.table
+
+JSCBISON += \
+    parser/Grammar.y
+
+RVCT_STUB_FILES += \
+    jit/JITStubs.cpp
+
+defineTest(addExtraCompiler) {
+    eval($${1}.CONFIG = target_predeps no_link)
+    eval($${1}.variable_out =)
+    eval($${1}.dependency_type = TYPE_C)
+
+    wkScript = $$eval($${1}.wkScript)
+    eval($${1}.depends += $$wkScript)
+
+    export($${1}.CONFIG)
+    export($${1}.variable_out)
+    export($${1}.dependency_type)
+    export($${1}.depends)
+
+    QMAKE_EXTRA_COMPILERS += $$1
+    generated_files.depends += compiler_$${1}_make_all
+    export(QMAKE_EXTRA_COMPILERS)
+    export(generated_files.depends)
+    return(true)
+}
+
+# GENERATOR 1-A: LUT creator
+lut.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.lut.h
+lut.input = LUT_FILES
+lut.wkScript = $$PWD/create_hash_table
+lut.commands = perl $$lut.wkScript ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
+lut.depends = ${QMAKE_FILE_NAME}
+addExtraCompiler(lut)
+
+# GENERATOR 1-B: particular LUT creator (for 1 file only)
+keywordlut.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}Lexer.lut.h
+keywordlut.input = KEYWORDLUT_FILES
+keywordlut.wkScript = $$PWD/create_hash_table
+keywordlut.commands = perl $$keywordlut.wkScript ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
+keywordlut.depends = ${QMAKE_FILE_NAME}
+addExtraCompiler(keywordlut)
+
+# GENERATOR 2: bison grammar
+jscbison.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.cpp
+jscbison.input = JSCBISON
+jscbison.commands = bison -d -p jscyy ${QMAKE_FILE_NAME} -o $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.c && $(MOVE) $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.c ${QMAKE_FILE_OUT} && $(MOVE) $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.h $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.h
+jscbison.depends = ${QMAKE_FILE_NAME}
+addExtraCompiler(jscbison)
+
+# GENERATOR 3: JIT Stub functions for RVCT
+rvctstubs.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}Generated${QMAKE_FILE_BASE}_RVCT.h
+rvctstubs.wkScript = $$PWD/create_rvct_stubs
+rvctstubs.commands = perl $$rvctstubs.wkScript ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
+rvctstubs.depends = ${QMAKE_FILE_NAME}
+rvctstubs.input = RVCT_STUB_FILES
+rvctstubs.CONFIG += no_link
+addExtraCompiler(rvctstubs)
+
+# GENERATOR: "chartables.c": compile and execute the chartables generator (and add it to sources)
+win32-msvc*|wince*: PREPROCESSOR = "--preprocessor=\"$$QMAKE_CC /E\""
+ctgen.output = $$JSC_GENERATED_SOURCES_DIR/chartables.c
+ctgen.wkScript = $$PWD/pcre/dftables
+ctgen.input = ctgen.wkScript
+ctgen.commands = perl $$ctgen.wkScript ${QMAKE_FILE_OUT} $$PREPROCESSOR
+ctgen.clean = ${QMAKE_FILE_OUT} ${QMAKE_VAR_JSC_GENERATED_SOURCES_DIR}${QMAKE_FILE_BASE}
+addExtraCompiler(ctgen)
+
index d376b78899901fd9789c3726078706dfa7de0c01..7ac6a8ca8b8d38955603c5808bcfca0890ff9ec8 100644 (file)
@@ -45,6 +45,7 @@ javascriptcore_built_nosources += \
 
 javascriptcore_sources += \
        JavaScriptCore/API/APICast.h \
 
 javascriptcore_sources += \
        JavaScriptCore/API/APICast.h \
+       JavaScriptCore/API/APIShims.h \
        JavaScriptCore/API/JSBase.cpp \
        JavaScriptCore/API/JSBasePrivate.h \
        JavaScriptCore/API/JSCallbackConstructor.cpp \
        JavaScriptCore/API/JSBase.cpp \
        JavaScriptCore/API/JSBasePrivate.h \
        JavaScriptCore/API/JSCallbackConstructor.cpp \
@@ -57,6 +58,7 @@ javascriptcore_sources += \
        JavaScriptCore/API/JSClassRef.cpp \
        JavaScriptCore/API/JSClassRef.h \
        JavaScriptCore/API/JSContextRef.cpp \
        JavaScriptCore/API/JSClassRef.cpp \
        JavaScriptCore/API/JSClassRef.h \
        JavaScriptCore/API/JSContextRef.cpp \
+       JavaScriptCore/API/JSContextRefPrivate.h \
        JavaScriptCore/API/JSObjectRef.cpp \
        JavaScriptCore/API/JSRetainPtr.h \
        JavaScriptCore/API/JSStringRef.cpp \
        JavaScriptCore/API/JSObjectRef.cpp \
        JavaScriptCore/API/JSRetainPtr.h \
        JavaScriptCore/API/JSStringRef.cpp \
@@ -96,8 +98,6 @@ javascriptcore_sources += \
        JavaScriptCore/bytecode/JumpTable.cpp \
        JavaScriptCore/bytecode/JumpTable.h \
        JavaScriptCore/bytecode/EvalCodeCache.h \
        JavaScriptCore/bytecode/JumpTable.cpp \
        JavaScriptCore/bytecode/JumpTable.h \
        JavaScriptCore/bytecode/EvalCodeCache.h \
-       JavaScriptCore/runtime/ExceptionHelpers.cpp \
-       JavaScriptCore/runtime/ExceptionHelpers.h \
        JavaScriptCore/bytecode/Instruction.h \
        JavaScriptCore/bytecompiler/Label.h \
        JavaScriptCore/interpreter/Interpreter.cpp \
        JavaScriptCore/bytecode/Instruction.h \
        JavaScriptCore/bytecompiler/Label.h \
        JavaScriptCore/interpreter/Interpreter.cpp \
@@ -135,14 +135,22 @@ javascriptcore_sources += \
        JavaScriptCore/icu/unicode/utf_old.h \
        JavaScriptCore/icu/unicode/utypes.h \
        JavaScriptCore/icu/unicode/uversion.h \
        JavaScriptCore/icu/unicode/utf_old.h \
        JavaScriptCore/icu/unicode/utypes.h \
        JavaScriptCore/icu/unicode/uversion.h \
+       JavaScriptCore/assembler/ARMAssembler.h \
+       JavaScriptCore/assembler/ARMAssembler.cpp \
        JavaScriptCore/assembler/X86Assembler.h \
        JavaScriptCore/assembler/AbstractMacroAssembler.h \
        JavaScriptCore/assembler/AssemblerBuffer.h \
        JavaScriptCore/assembler/X86Assembler.h \
        JavaScriptCore/assembler/AbstractMacroAssembler.h \
        JavaScriptCore/assembler/AssemblerBuffer.h \
+       JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h \
+       JavaScriptCore/assembler/CodeLocation.h \
+       JavaScriptCore/assembler/LinkBuffer.h \
        JavaScriptCore/assembler/MacroAssembler.h \
        JavaScriptCore/assembler/MacroAssembler.h \
+       JavaScriptCore/assembler/MacroAssemblerARM.h \
+       JavaScriptCore/assembler/MacroAssemblerARM.cpp \
        JavaScriptCore/assembler/MacroAssemblerCodeRef.h \
        JavaScriptCore/assembler/MacroAssemblerX86.h \
        JavaScriptCore/assembler/MacroAssemblerX86_64.h \
        JavaScriptCore/assembler/MacroAssemblerX86Common.h \
        JavaScriptCore/assembler/MacroAssemblerCodeRef.h \
        JavaScriptCore/assembler/MacroAssemblerX86.h \
        JavaScriptCore/assembler/MacroAssemblerX86_64.h \
        JavaScriptCore/assembler/MacroAssemblerX86Common.h \
+       JavaScriptCore/assembler/RepatchBuffer.h \
        JavaScriptCore/os-win32/stdbool.h \
        JavaScriptCore/os-win32/stdint.h \
        JavaScriptCore/pcre/pcre.h \
        JavaScriptCore/os-win32/stdbool.h \
        JavaScriptCore/os-win32/stdint.h \
        JavaScriptCore/pcre/pcre.h \
@@ -154,8 +162,6 @@ javascriptcore_sources += \
        JavaScriptCore/pcre/pcre_xclass.cpp \
        JavaScriptCore/pcre/ucpinternal.h \
        JavaScriptCore/profiler/CallIdentifier.h \
        JavaScriptCore/pcre/pcre_xclass.cpp \
        JavaScriptCore/pcre/ucpinternal.h \
        JavaScriptCore/profiler/CallIdentifier.h \
-       JavaScriptCore/profiler/HeavyProfile.cpp \
-       JavaScriptCore/profiler/HeavyProfile.h \
        JavaScriptCore/profiler/Profile.cpp \
        JavaScriptCore/profiler/Profile.h \
        JavaScriptCore/profiler/ProfileGenerator.cpp \
        JavaScriptCore/profiler/Profile.cpp \
        JavaScriptCore/profiler/Profile.h \
        JavaScriptCore/profiler/ProfileGenerator.cpp \
@@ -164,14 +170,14 @@ javascriptcore_sources += \
        JavaScriptCore/profiler/ProfileNode.h \
        JavaScriptCore/profiler/Profiler.cpp \
        JavaScriptCore/profiler/Profiler.h \
        JavaScriptCore/profiler/ProfileNode.h \
        JavaScriptCore/profiler/Profiler.cpp \
        JavaScriptCore/profiler/Profiler.h \
-       JavaScriptCore/profiler/TreeProfile.cpp \
-       JavaScriptCore/profiler/TreeProfile.h \
        JavaScriptCore/interpreter/CachedCall.h \
        JavaScriptCore/interpreter/CallFrame.cpp \
        JavaScriptCore/interpreter/CallFrame.h \
        JavaScriptCore/interpreter/CallFrameClosure.h \
        JavaScriptCore/interpreter/CachedCall.h \
        JavaScriptCore/interpreter/CallFrame.cpp \
        JavaScriptCore/interpreter/CallFrame.h \
        JavaScriptCore/interpreter/CallFrameClosure.h \
-       JavaScriptCore/runtime/TimeoutChecker.cpp \
-       JavaScriptCore/runtime/TimeoutChecker.h \
+       JavaScriptCore/runtime/ExceptionHelpers.cpp \
+       JavaScriptCore/runtime/ExceptionHelpers.h \
+       JavaScriptCore/runtime/Executable.cpp \
+       JavaScriptCore/runtime/Executable.h \
        JavaScriptCore/runtime/InitializeThreading.cpp \
        JavaScriptCore/runtime/InitializeThreading.h \
        JavaScriptCore/runtime/JSActivation.cpp \
        JavaScriptCore/runtime/InitializeThreading.cpp \
        JavaScriptCore/runtime/InitializeThreading.h \
        JavaScriptCore/runtime/JSActivation.cpp \
@@ -186,16 +192,27 @@ javascriptcore_sources += \
        JavaScriptCore/runtime/JSONObject.h \
        JavaScriptCore/runtime/JSPropertyNameIterator.cpp \
        JavaScriptCore/runtime/JSPropertyNameIterator.h \
        JavaScriptCore/runtime/JSONObject.h \
        JavaScriptCore/runtime/JSPropertyNameIterator.cpp \
        JavaScriptCore/runtime/JSPropertyNameIterator.h \
+       JavaScriptCore/runtime/JSZombie.h \
        JavaScriptCore/runtime/LiteralParser.cpp \
        JavaScriptCore/runtime/LiteralParser.h \
        JavaScriptCore/runtime/LiteralParser.cpp \
        JavaScriptCore/runtime/LiteralParser.h \
+       JavaScriptCore/runtime/MarkStack.cpp \
+       JavaScriptCore/runtime/MarkStack.h \
+       JavaScriptCore/runtime/NumericStrings.h \
+       JavaScriptCore/runtime/PropertyDescriptor.h \
+       JavaScriptCore/runtime/PropertyDescriptor.cpp \
        JavaScriptCore/runtime/SmallStrings.cpp \
        JavaScriptCore/runtime/SmallStrings.h \
        JavaScriptCore/runtime/SmallStrings.cpp \
        JavaScriptCore/runtime/SmallStrings.h \
+       JavaScriptCore/runtime/StringBuilder.h \
        JavaScriptCore/runtime/Structure.cpp \
        JavaScriptCore/runtime/Structure.h \
        JavaScriptCore/runtime/StructureChain.cpp \
        JavaScriptCore/runtime/StructureChain.h \
        JavaScriptCore/runtime/StructureTransitionTable.h \
        JavaScriptCore/runtime/Structure.cpp \
        JavaScriptCore/runtime/Structure.h \
        JavaScriptCore/runtime/StructureChain.cpp \
        JavaScriptCore/runtime/StructureChain.h \
        JavaScriptCore/runtime/StructureTransitionTable.h \
-       JavaScriptCore/runtime/TypeInfo.h \
+       JavaScriptCore/runtime/TimeoutChecker.cpp \
+       JavaScriptCore/runtime/TimeoutChecker.h \
+       JavaScriptCore/runtime/JSTypeInfo.h \
+       JavaScriptCore/runtime/WeakGCMap.h \
+       JavaScriptCore/runtime/WeakGCPtr.h \
        JavaScriptCore/wrec/CharacterClass.h \
        JavaScriptCore/wrec/CharacterClassConstructor.h \
        JavaScriptCore/wrec/Escapes.h \
        JavaScriptCore/wrec/CharacterClass.h \
        JavaScriptCore/wrec/CharacterClassConstructor.h \
        JavaScriptCore/wrec/Escapes.h \
@@ -212,7 +229,6 @@ javascriptcore_sources += \
        JavaScriptCore/wtf/ByteArray.cpp \
        JavaScriptCore/wtf/ByteArray.h \
        JavaScriptCore/wtf/CrossThreadRefCounted.h \
        JavaScriptCore/wtf/ByteArray.cpp \
        JavaScriptCore/wtf/ByteArray.h \
        JavaScriptCore/wtf/CrossThreadRefCounted.h \
-       JavaScriptCore/wtf/OwnFastMallocPtr.h \
        JavaScriptCore/wtf/CurrentTime.cpp \
        JavaScriptCore/wtf/CurrentTime.h \
        JavaScriptCore/wtf/DateMath.cpp \
        JavaScriptCore/wtf/CurrentTime.cpp \
        JavaScriptCore/wtf/CurrentTime.h \
        JavaScriptCore/wtf/DateMath.cpp \
@@ -220,8 +236,6 @@ javascriptcore_sources += \
        JavaScriptCore/wtf/Deque.h \
        JavaScriptCore/wtf/DisallowCType.h \
        JavaScriptCore/wtf/Forward.h \
        JavaScriptCore/wtf/Deque.h \
        JavaScriptCore/wtf/DisallowCType.h \
        JavaScriptCore/wtf/Forward.h \
-       JavaScriptCore/wtf/GOwnPtr.cpp \
-       JavaScriptCore/wtf/GOwnPtr.h \
        JavaScriptCore/wtf/GetPtr.h \
        JavaScriptCore/wtf/HashCountedSet.h \
        JavaScriptCore/wtf/HashFunctions.h \
        JavaScriptCore/wtf/GetPtr.h \
        JavaScriptCore/wtf/HashCountedSet.h \
        JavaScriptCore/wtf/HashFunctions.h \
@@ -241,11 +255,13 @@ javascriptcore_sources += \
        JavaScriptCore/wtf/Noncopyable.h \
        JavaScriptCore/wtf/NotFound.h \
        JavaScriptCore/wtf/OwnArrayPtr.h \
        JavaScriptCore/wtf/Noncopyable.h \
        JavaScriptCore/wtf/NotFound.h \
        JavaScriptCore/wtf/OwnArrayPtr.h \
+       JavaScriptCore/wtf/OwnFastMallocPtr.h \
        JavaScriptCore/wtf/OwnPtr.h \
        JavaScriptCore/wtf/OwnPtrCommon.h \
        JavaScriptCore/wtf/PassOwnPtr.h \
        JavaScriptCore/wtf/PassRefPtr.h \
        JavaScriptCore/wtf/Platform.h \
        JavaScriptCore/wtf/OwnPtr.h \
        JavaScriptCore/wtf/OwnPtrCommon.h \
        JavaScriptCore/wtf/PassOwnPtr.h \
        JavaScriptCore/wtf/PassRefPtr.h \
        JavaScriptCore/wtf/Platform.h \
+       JavaScriptCore/wtf/PossiblyNull.h \
        JavaScriptCore/wtf/PtrAndFlags.h \
        JavaScriptCore/wtf/RandomNumber.cpp \
        JavaScriptCore/wtf/RandomNumber.h \
        JavaScriptCore/wtf/PtrAndFlags.h \
        JavaScriptCore/wtf/RandomNumber.cpp \
        JavaScriptCore/wtf/RandomNumber.h \
@@ -259,18 +275,25 @@ javascriptcore_sources += \
        JavaScriptCore/wtf/SegmentedVector.h \
        JavaScriptCore/wtf/StdLibExtras.h \
        JavaScriptCore/wtf/StringExtras.h \
        JavaScriptCore/wtf/SegmentedVector.h \
        JavaScriptCore/wtf/StdLibExtras.h \
        JavaScriptCore/wtf/StringExtras.h \
+       JavaScriptCore/wtf/StringHashFunctions.h \
        JavaScriptCore/wtf/TCPackedCache.h \
        JavaScriptCore/wtf/TCPageMap.h \
        JavaScriptCore/wtf/TCSpinLock.h \
        JavaScriptCore/wtf/TCPackedCache.h \
        JavaScriptCore/wtf/TCPageMap.h \
        JavaScriptCore/wtf/TCSpinLock.h \
-       JavaScriptCore/wtf/ThreadSpecific.h \
-       JavaScriptCore/wtf/Threading.h \
+       JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp \
+       JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h \
        JavaScriptCore/wtf/Threading.cpp \
        JavaScriptCore/wtf/Threading.cpp \
+       JavaScriptCore/wtf/Threading.h \
        JavaScriptCore/wtf/ThreadingPthreads.cpp \
        JavaScriptCore/wtf/ThreadingPthreads.cpp \
+       JavaScriptCore/wtf/ThreadSpecific.h \
        JavaScriptCore/wtf/TypeTraits.cpp \
        JavaScriptCore/wtf/TypeTraits.h \
        JavaScriptCore/wtf/UnusedParam.h \
        JavaScriptCore/wtf/Vector.h \
        JavaScriptCore/wtf/VectorTraits.h \
        JavaScriptCore/wtf/TypeTraits.cpp \
        JavaScriptCore/wtf/TypeTraits.h \
        JavaScriptCore/wtf/UnusedParam.h \
        JavaScriptCore/wtf/Vector.h \
        JavaScriptCore/wtf/VectorTraits.h \
+       JavaScriptCore/wtf/gtk/GOwnPtr.cpp \
+       JavaScriptCore/wtf/gtk/GOwnPtr.h \
+       JavaScriptCore/wtf/gtk/GRefPtr.cpp \
+       JavaScriptCore/wtf/gtk/GRefPtr.h \
        JavaScriptCore/wtf/gtk/MainThreadGtk.cpp \
        JavaScriptCore/wtf/gtk/ThreadingGtk.cpp \
        JavaScriptCore/wtf/unicode/Collator.h \
        JavaScriptCore/wtf/gtk/MainThreadGtk.cpp \
        JavaScriptCore/wtf/gtk/ThreadingGtk.cpp \
        JavaScriptCore/wtf/unicode/Collator.h \
@@ -282,10 +305,12 @@ javascriptcore_sources += \
 if TARGET_WIN32
 javascriptcore_sources += \
        JavaScriptCore/wtf/ThreadSpecificWin.cpp \
 if TARGET_WIN32
 javascriptcore_sources += \
        JavaScriptCore/wtf/ThreadSpecificWin.cpp \
-       JavaScriptCore/jit/ExecutableAllocatorWin.cpp
+       JavaScriptCore/jit/ExecutableAllocatorWin.cpp \
+       JavaScriptCore/runtime/MarkStackWin.cpp
 else
 javascriptcore_sources += \
 else
 javascriptcore_sources += \
-       JavaScriptCore/jit/ExecutableAllocatorPosix.cpp
+       JavaScriptCore/jit/ExecutableAllocatorPosix.cpp \
+       JavaScriptCore/runtime/MarkStackPosix.cpp
 endif
 
 # ----
 endif
 
 # ----
@@ -318,17 +343,12 @@ javascriptcore_sources += \
        JavaScriptCore/yarr/RegexParser.h \
        JavaScriptCore/yarr/RegexPattern.h
 
        JavaScriptCore/yarr/RegexParser.h \
        JavaScriptCore/yarr/RegexPattern.h
 
-# Debug build
-if ENABLE_DEBUG
-javascriptcore_built_sources += \
-       DerivedSources/Grammar.cpp \
-       DerivedSources/Grammar.h
-
 javascriptcore_sources += \
        JavaScriptCore/interpreter/RegisterFile.cpp \
        JavaScriptCore/interpreter/RegisterFile.h \
        JavaScriptCore/bytecompiler/BytecodeGenerator.cpp \
        JavaScriptCore/bytecompiler/BytecodeGenerator.h \
 javascriptcore_sources += \
        JavaScriptCore/interpreter/RegisterFile.cpp \
        JavaScriptCore/interpreter/RegisterFile.h \
        JavaScriptCore/bytecompiler/BytecodeGenerator.cpp \
        JavaScriptCore/bytecompiler/BytecodeGenerator.h \
+       JavaScriptCore/bytecompiler/NodesCodegen.cpp \
        JavaScriptCore/bytecompiler/LabelScope.h \
        JavaScriptCore/debugger/Debugger.cpp \
        JavaScriptCore/debugger/Debugger.h \
        JavaScriptCore/bytecompiler/LabelScope.h \
        JavaScriptCore/debugger/Debugger.cpp \
        JavaScriptCore/debugger/Debugger.h \
@@ -377,6 +397,7 @@ javascriptcore_sources += \
        JavaScriptCore/runtime/DateConversion.h \
        JavaScriptCore/runtime/DateInstance.cpp \
        JavaScriptCore/runtime/DateInstance.h \
        JavaScriptCore/runtime/DateConversion.h \
        JavaScriptCore/runtime/DateInstance.cpp \
        JavaScriptCore/runtime/DateInstance.h \
+       JavaScriptCore/runtime/DateInstanceCache.h \
        JavaScriptCore/runtime/DatePrototype.cpp \
        JavaScriptCore/runtime/DatePrototype.h \
        JavaScriptCore/runtime/Error.cpp \
        JavaScriptCore/runtime/DatePrototype.cpp \
        JavaScriptCore/runtime/DatePrototype.h \
        JavaScriptCore/runtime/Error.cpp \
@@ -402,6 +423,8 @@ javascriptcore_sources += \
        JavaScriptCore/runtime/Completion.cpp \
        JavaScriptCore/runtime/JSArray.cpp \
        JavaScriptCore/runtime/JSArray.h \
        JavaScriptCore/runtime/Completion.cpp \
        JavaScriptCore/runtime/JSArray.cpp \
        JavaScriptCore/runtime/JSArray.h \
+       JavaScriptCore/runtime/JSAPIValueWrapper.cpp \
+       JavaScriptCore/runtime/JSAPIValueWrapper.h \
        JavaScriptCore/runtime/JSCell.cpp \
        JavaScriptCore/runtime/JSCell.h \
        JavaScriptCore/runtime/JSFunction.cpp \
        JavaScriptCore/runtime/JSCell.cpp \
        JavaScriptCore/runtime/JSCell.h \
        JavaScriptCore/runtime/JSFunction.cpp \
@@ -482,6 +505,9 @@ javascriptcore_sources += \
        JavaScriptCore/runtime/Tracing.h \
        JavaScriptCore/runtime/UString.cpp \
        JavaScriptCore/runtime/UString.h \
        JavaScriptCore/runtime/Tracing.h \
        JavaScriptCore/runtime/UString.cpp \
        JavaScriptCore/runtime/UString.h \
+       JavaScriptCore/runtime/UStringImpl.cpp \
+       JavaScriptCore/runtime/UStringImpl.h \
+       JavaScriptCore/runtime/WeakRandom.h \
        JavaScriptCore/wtf/FastAllocBase.h \
        JavaScriptCore/wtf/FastMalloc.cpp \
        JavaScriptCore/wtf/FastMalloc.h \
        JavaScriptCore/wtf/FastAllocBase.h \
        JavaScriptCore/wtf/FastMalloc.cpp \
        JavaScriptCore/wtf/FastMalloc.h \
@@ -491,17 +517,10 @@ javascriptcore_sources += \
        JavaScriptCore/wtf/dtoa.cpp \
        JavaScriptCore/wtf/dtoa.h
 
        JavaScriptCore/wtf/dtoa.cpp \
        JavaScriptCore/wtf/dtoa.h
 
-else
-javascriptcore_built_nosources += \
+javascriptcore_built_sources += \
        DerivedSources/Grammar.cpp \
        DerivedSources/Grammar.h
 
        DerivedSources/Grammar.cpp \
        DerivedSources/Grammar.h
 
-javascriptcore_sources += \
-       JavaScriptCore/AllInOneFile.cpp \
-       JavaScriptCore/parser/ParserArena.cpp \
-       JavaScriptCore/parser/ParserArena.h
-endif # END ENABLE_DEBUG
-
 DerivedSources/Grammar.h: DerivedSources/Grammar.cpp;
 
 DerivedSources/Grammar.cpp: $(srcdir)/JavaScriptCore/parser/Grammar.y
 DerivedSources/Grammar.h: DerivedSources/Grammar.cpp;
 
 DerivedSources/Grammar.cpp: $(srcdir)/JavaScriptCore/parser/Grammar.y
index 17949b026d02c59ec1ecda5c7d6f201fd871dd5d..77c9eb80491c9dbfa6bf308e6aa987f6abbdf8b5 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
        <key>CFBundleDevelopmentRegion</key>
 <plist version="1.0">
 <dict>
        <key>CFBundleDevelopmentRegion</key>
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundleGetInfoString</key>
        <key>CFBundleExecutable</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>${BUNDLE_VERSION}, Copyright 2003-2009 Apple Inc.; Copyright 1999-2001 Harri Porten &lt;porten@kde.org&gt;; Copyright 2001 Peter Kelly &lt;pmk@post.com&gt;; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies.</string>
+       <string>${BUNDLE_VERSION}, Copyright 2003-2010 Apple Inc.; Copyright 1999-2001 Harri Porten &lt;porten@kde.org&gt;; Copyright 2001 Peter Kelly &lt;pmk@post.com&gt;; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies.</string>
        <key>CFBundleIdentifier</key>
        <string>com.apple.${PRODUCT_NAME}</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <key>CFBundleIdentifier</key>
        <string>com.apple.${PRODUCT_NAME}</string>
        <key>CFBundleInfoDictionaryVersion</key>
index 6d9af9bb629b3dce6a4d5fe119d99d5ac77ea574..aa82120981d88bdb62e8d0f17cb0817f4fab82ee 100644 (file)
@@ -2,6 +2,7 @@ _JSCheckScriptSyntax
 _JSClassCreate
 _JSClassRelease
 _JSClassRetain
 _JSClassCreate
 _JSClassRelease
 _JSClassRetain
+_JSContextGetGlobalContext
 _JSContextGetGlobalObject
 _JSContextGetGroup
 _JSContextGroupCreate
 _JSContextGetGlobalObject
 _JSContextGetGroup
 _JSContextGroupCreate
@@ -78,6 +79,7 @@ _JSValueToNumber
 _JSValueToObject
 _JSValueToStringCopy
 _JSValueUnprotect
 _JSValueToObject
 _JSValueToStringCopy
 _JSValueUnprotect
+_WebCoreWebThreadIsLockedOrDisabled
 _WTFLog
 _WTFLogVerbose
 _WTFReportArgumentAssertionFailure
 _WTFLog
 _WTFLogVerbose
 _WTFReportArgumentAssertionFailure
@@ -89,101 +91,120 @@ __Z12jsRegExpFreeP8JSRegExp
 __Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
 __Z15jsRegExpExecutePK8JSRegExpPKtiiPii
 __ZN14OpaqueJSString6createERKN3JSC7UStringE
 __Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
 __Z15jsRegExpExecutePK8JSRegExpPKtiiPii
 __ZN14OpaqueJSString6createERKN3JSC7UStringE
-__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPNS_7UString3RepE
-__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_7UString3RepE
-__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_12JSGlobalDataEPNS_7UString3RepE 
-__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_9ExecStateEPNS_7UString3RepE 
+__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPNS_11UStringImplE
+__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_11UStringImplE
+__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_12JSGlobalDataEPNS_11UStringImplE
+__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_9ExecStateEPNS_11UStringImplE
 __ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
 __ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
-__ZN3JSC10Identifier5equalEPKNS_7UString3RepEPKc
-__ZN3JSC10JSFunction4infoE
-__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
+__ZN3JSC10Identifier5equalEPKNS_11UStringImplEPKc
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
 __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
 __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
 __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE
 __ZN3JSC11JSByteArray15createStructureENS_7JSValueE
 __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
 __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
 __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE
 __ZN3JSC11JSByteArray15createStructureENS_7JSValueE
-__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
+__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
 __ZN3JSC11ParserArena5resetEv
 __ZN3JSC11ParserArena5resetEv
+__ZN3JSC11UStringImpl12sharedBufferEv
+__ZN3JSC11UStringImpl6s_nullE
+__ZN3JSC11UStringImpl7s_emptyE
+__ZN3JSC11UStringImplD1Ev
 __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
 __ZN3JSC12DateInstance4infoE
 __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
 __ZN3JSC12DateInstance4infoE
+__ZN3JSC12DateInstanceC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEd
+__ZN3JSC12DateInstanceC1EPNS_9ExecStateEd
 __ZN3JSC12JSGlobalData10ClientDataD2Ev
 __ZN3JSC12JSGlobalData10ClientDataD2Ev
+__ZN3JSC12JSGlobalData11jsArrayVPtrE
 __ZN3JSC12JSGlobalData12createLeakedEv
 __ZN3JSC12JSGlobalData12createLeakedEv
+__ZN3JSC12JSGlobalData12jsStringVPtrE
+__ZN3JSC12JSGlobalData12stopSamplingEv
+__ZN3JSC12JSGlobalData13startSamplingEv
+__ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
+__ZN3JSC12JSGlobalData14resetDateCacheEv
 __ZN3JSC12JSGlobalData14sharedInstanceEv
 __ZN3JSC12JSGlobalData14sharedInstanceEv
-__ZN3JSC12JSGlobalData6createEb
+__ZN3JSC12JSGlobalData6createEv
 __ZN3JSC12JSGlobalDataD1Ev
 __ZN3JSC12JSGlobalDataD1Ev
-__ZN3JSC12SamplingTool4dumpEPNS_9ExecStateE
 __ZN3JSC12SamplingTool5setupEv
 __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
 __ZN3JSC12SamplingTool5setupEv
 __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
+__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
 __ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC12StringObject14toThisJSStringEPNS_9ExecStateE
-__ZN3JSC12StringObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
 __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC12StringObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC12StringObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC12StringObject4infoE
 __ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC12StringObject4infoE
-__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringE
+__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7UStringE
 __ZN3JSC12jsNumberCellEPNS_9ExecStateEd
 __ZN3JSC12nonInlineNaNEv
 __ZN3JSC13SamplingFlags4stopEv
 __ZN3JSC13SamplingFlags5startEv
 __ZN3JSC13SamplingFlags7s_flagsE
 __ZN3JSC13StatementNode6setLocEii
 __ZN3JSC12jsNumberCellEPNS_9ExecStateEd
 __ZN3JSC12nonInlineNaNEv
 __ZN3JSC13SamplingFlags4stopEv
 __ZN3JSC13SamplingFlags5startEv
 __ZN3JSC13SamplingFlags7s_flagsE
 __ZN3JSC13StatementNode6setLocEii
-__ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE
 __ZN3JSC14JSGlobalObject10globalExecEv
 __ZN3JSC14JSGlobalObject10globalExecEv
-__ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
-__ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
+__ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
+__ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
+__ZN3JSC14JSGlobalObject12markChildrenERNS_9MarkStackE
 __ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
 __ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC14JSGlobalObject25destroyJSGlobalObjectDataEPv
 __ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE  
 __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
 __ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE  
 __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
-__ZN3JSC14JSGlobalObject4markEv
 __ZN3JSC14JSGlobalObjectD2Ev
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
 __ZN3JSC14SamplingThread4stopEv
 __ZN3JSC14SamplingThread5startEj
 __ZN3JSC14JSGlobalObjectD2Ev
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
 __ZN3JSC14SamplingThread4stopEv
 __ZN3JSC14SamplingThread5startEj
+__ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
 __ZN3JSC14TimeoutChecker5resetEv
 __ZN3JSC14TimeoutChecker5resetEv
-__ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC15JSWrapperObject4markEv
+__ZN3JSC15JSWrapperObject12markChildrenERNS_9MarkStackE
+__ZN3JSC15createTypeErrorEPNS_9ExecStateEPKc
 __ZN3JSC15toInt32SlowCaseEdRb
 __ZN3JSC15toInt32SlowCaseEdRb
-__ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm
-__ZN3JSC16FunctionBodyNode14copyParametersEv
-__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_IPNS_12FuncDeclNodeELm0EEERKNS_10SourceCodeEji
 __ZN3JSC16InternalFunction4infoE
 __ZN3JSC16InternalFunction4infoE
-__ZN3JSC16InternalFunction4nameEPNS_12JSGlobalDataE
-__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF10PassRefPtrINS_9StructureEEERKNS_10IdentifierE
+__ZN3JSC16InternalFunction4nameEPNS_9ExecStateE
+__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_10IdentifierE
 __ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3JSC16toUInt32SlowCaseEdRb
 __ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb
 __ZN3JSC16toUInt32SlowCaseEdRb
 __ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb
-__ZN3JSC17PropertyNameArray3addEPNS_7UString3RepE
-__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
+__ZN3JSC17PropertyNameArray3addEPNS_11UStringImplE
+__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
 __ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectES6_RKNS_7ArgListEE
 __ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
 __ZN3JSC18DebuggerActivationC1EPNS_8JSObjectE
 __ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectES6_RKNS_7ArgListEE
 __ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
 __ZN3JSC18DebuggerActivationC1EPNS_8JSObjectE
-__ZN3JSC19constructEmptyArrayEPNS_9ExecStateE
+__ZN3JSC18PropertyDescriptor11setWritableEb
+__ZN3JSC18PropertyDescriptor12setUndefinedEv
+__ZN3JSC18PropertyDescriptor13setDescriptorENS_7JSValueEj
+__ZN3JSC18PropertyDescriptor13setEnumerableEb
+__ZN3JSC18PropertyDescriptor15setConfigurableEb
+__ZN3JSC18PropertyDescriptor17defaultAttributesE
+__ZN3JSC18PropertyDescriptor21setAccessorDescriptorENS_7JSValueES1_j
+__ZN3JSC18PropertyDescriptor9setGetterENS_7JSValueE
+__ZN3JSC18PropertyDescriptor9setSetterENS_7JSValueE
 __ZN3JSC19initializeThreadingEv
 __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
 __ZN3JSC19initializeThreadingEv
 __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
-__ZN3JSC20constructEmptyObjectEPNS_9ExecStateE
 __ZN3JSC23AbstractSamplingCounter4dumpEv
 __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC23AbstractSamplingCounter4dumpEv
 __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
 __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
 __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
-__ZN3JSC4Heap11objectCountEv
+__ZN3JSC25g_identifierTableSpecificE
+__ZN3JSC29createIdentifierTableSpecificEv
+__ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
+__ZN3JSC3NaNE
 __ZN3JSC4Heap14primaryHeapEndEv
 __ZN3JSC4Heap15recordExtraCostEm
 __ZN3JSC4Heap16primaryHeapBeginEv
 __ZN3JSC4Heap14primaryHeapEndEv
 __ZN3JSC4Heap15recordExtraCostEm
 __ZN3JSC4Heap16primaryHeapBeginEv
+__ZN3JSC4Heap17collectAllGarbageEv
 __ZN3JSC4Heap17globalObjectCountEv
 __ZN3JSC4Heap20protectedObjectCountEv
 __ZN3JSC4Heap17globalObjectCountEv
 __ZN3JSC4Heap20protectedObjectCountEv
-__ZN3JSC4Heap24setGCProtectNeedsLockingEv
 __ZN3JSC4Heap25protectedObjectTypeCountsEv
 __ZN3JSC4Heap26protectedGlobalObjectCountEv
 __ZN3JSC4Heap25protectedObjectTypeCountsEv
 __ZN3JSC4Heap26protectedGlobalObjectCountEv
-__ZN3JSC4Heap4heapENS_7JSValueE  
 __ZN3JSC4Heap6isBusyEv
 __ZN3JSC4Heap6isBusyEv
-__ZN3JSC4Heap7collectEv
 __ZN3JSC4Heap7destroyEv
 __ZN3JSC4Heap7protectENS_7JSValueE
 __ZN3JSC4Heap8allocateEm
 __ZN3JSC4Heap9unprotectENS_7JSValueE
 __ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
 __ZN3JSC4Heap7destroyEv
 __ZN3JSC4Heap7protectENS_7JSValueE
 __ZN3JSC4Heap8allocateEm
 __ZN3JSC4Heap9unprotectENS_7JSValueE
 __ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
-__ZN3JSC5equalEPKNS_7UString3RepES3_
+__ZN3JSC5equalEPKNS_11UStringImplES2_
 __ZN3JSC6JSCell11getCallDataERNS_8CallDataE
 __ZN3JSC6JSCell11getJSNumberEv
 __ZN3JSC6JSCell14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC6JSCell11getCallDataERNS_8CallDataE
 __ZN3JSC6JSCell11getJSNumberEv
 __ZN3JSC6JSCell14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
@@ -192,74 +213,76 @@ __ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE
 __ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
 __ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
 __ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC6JSCell18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
 __ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC6JSCell3putEPNS_9ExecStateEjNS_7JSValueE  
 __ZN3JSC6JSCell9getObjectEv
 __ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC6JSCell3putEPNS_9ExecStateEjNS_7JSValueE  
 __ZN3JSC6JSCell9getObjectEv
-__ZN3JSC6JSCellnwEmPNS_9ExecStateE
+__ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
 __ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
 __ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
-__ZN3JSC6JSLock12DropAllLocksC1Eb
 __ZN3JSC6JSLock12DropAllLocksD1Ev
 __ZN3JSC6JSLock12DropAllLocksD1Ev
-__ZN3JSC6JSLock4lockEb
-__ZN3JSC6JSLock6unlockEb
+__ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
+__ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
 __ZN3JSC6JSLock9lockCountEv
 __ZN3JSC6JSLockC1EPNS_9ExecStateE
 __ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
 __ZN3JSC7CStringD1Ev
 __ZN3JSC7CStringaSERKS0_
 __ZN3JSC7JSArray4infoE
 __ZN3JSC6JSLock9lockCountEv
 __ZN3JSC6JSLockC1EPNS_9ExecStateE
 __ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
 __ZN3JSC7CStringD1Ev
 __ZN3JSC7CStringaSERKS0_
 __ZN3JSC7JSArray4infoE
+__ZN3JSC7JSArray9setLengthEj
+__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7ArgListE
 __ZN3JSC7Profile10restoreAllEv
 __ZN3JSC7Profile5focusEPKNS_11ProfileNodeE
 __ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE
 __ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
 __ZN3JSC7Profile10restoreAllEv
 __ZN3JSC7Profile5focusEPKNS_11ProfileNodeE
 __ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE
 __ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
-__ZN3JSC7UString3Rep11computeHashEPKci
-__ZN3JSC7UString3Rep11computeHashEPKti
-__ZN3JSC7UString3Rep12sharedBufferEv
-__ZN3JSC7UString3Rep14createFromUTF8EPKc
-__ZN3JSC7UString3Rep14nullBaseStringE
-__ZN3JSC7UString3Rep6createEPtiN3WTF10PassRefPtrINS3_21CrossThreadRefCountedINS3_16OwnFastMallocPtrItEEEEEE
-__ZN3JSC7UString3Rep7destroyEv
 __ZN3JSC7UString4fromEd
 __ZN3JSC7UString4fromEi
 __ZN3JSC7UString4fromEj
 __ZN3JSC7UString4fromEl
 __ZN3JSC7UString4fromEd
 __ZN3JSC7UString4fromEi
 __ZN3JSC7UString4fromEj
 __ZN3JSC7UString4fromEl
-__ZN3JSC7UString6appendEPKc
-__ZN3JSC7UString6appendERKS0_
 __ZN3JSC7UStringC1EPKc
 __ZN3JSC7UStringC1EPKti
 __ZN3JSC7UStringaSEPKc
 __ZN3JSC7UStringC1EPKc
 __ZN3JSC7UStringC1EPKti
 __ZN3JSC7UStringaSEPKc
+__ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE
 __ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
 __ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
 __ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
 __ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
-__ZN3JSC8DebuggerC2Ev
 __ZN3JSC8DebuggerD2Ev
 __ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
 __ZN3JSC8DebuggerD2Ev
 __ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
-__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
-__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
+__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
+__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
 __ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC8JSObject12markChildrenERNS_9MarkStackE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
 __ZN3JSC8JSObject15unwrappedObjectEv
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
 __ZN3JSC8JSObject15unwrappedObjectEv
-__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
+__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3JSC8JSObject17createInheritorIDEv
 __ZN3JSC8JSObject17createInheritorIDEv
+__ZN3JSC8JSObject17defineOwnPropertyEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorEb
 __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotE
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateEjNS_7JSValueEj
 __ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
 __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotE
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateEjNS_7JSValueEj
 __ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
+__ZN3JSC8JSObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC8JSObject21getPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_7JSValueE  
 __ZN3JSC8JSObject23allocatePropertyStorageEmm
 __ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_7JSValueE  
 __ZN3JSC8JSObject23allocatePropertyStorageEmm
+__ZN3JSC8JSObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE  
 __ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE  
-__ZN3JSC8JSObject4markEv
+__ZN3JSC8JSString4RopeD1Ev
 __ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC8Profiler8profilerEv
 __ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
 __ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC8Profiler8profilerEv
 __ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
-__ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE
 __ZN3JSC9CodeBlockD1Ev
 __ZN3JSC9CodeBlockD2Ev
 __ZN3JSC9CodeBlockD1Ev
 __ZN3JSC9CodeBlockD2Ev
-__ZN3JSC9Structure13hasTransitionEPNS_7UString3RepEj
+__ZN3JSC9MarkStack10s_pageSizeE
+__ZN3JSC9MarkStack12releaseStackEPvm
+__ZN3JSC9MarkStack13allocateStackEm
+__ZN3JSC9MarkStack18initializePagesizeEv
+__ZN3JSC9Structure13hasTransitionEPNS_11UStringImplEj
 __ZN3JSC9Structure17stopIgnoringLeaksEv
 __ZN3JSC9Structure18startIgnoringLeaksEv
 __ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
 __ZN3JSC9Structure17stopIgnoringLeaksEv
 __ZN3JSC9Structure18startIgnoringLeaksEv
 __ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
@@ -268,9 +291,9 @@ __ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_7JSValueE
 __ZN3JSC9Structure27despecifyDictionaryFunctionERKNS_10IdentifierE
 __ZN3JSC9Structure27despecifyFunctionTransitionEPS0_RKNS_10IdentifierE
 __ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEjPNS_6JSCellE
 __ZN3JSC9Structure27despecifyDictionaryFunctionERKNS_10IdentifierE
 __ZN3JSC9Structure27despecifyFunctionTransitionEPS0_RKNS_10IdentifierE
 __ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEjPNS_6JSCellE
-__ZN3JSC9Structure3getEPKNS_7UString3RepERjRPNS_6JSCellE
+__ZN3JSC9Structure3getEPKNS_11UStringImplERjRPNS_6JSCellE
 __ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
 __ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
-__ZN3JSC9StructureC1ENS_7JSValueERKNS_8TypeInfoE
+__ZN3JSC9StructureC1ENS_7JSValueERKNS_8TypeInfoEj
 __ZN3JSC9StructureD1Ev
 __ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
 __ZN3JSCeqERKNS_7UStringEPKc
 __ZN3JSC9StructureD1Ev
 __ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
 __ZN3JSCeqERKNS_7UStringEPKc
@@ -287,6 +310,7 @@ __ZN3WTF12isMainThreadEv
 __ZN3WTF12randomNumberEv
 __ZN3WTF13currentThreadEv
 __ZN3WTF13tryFastCallocEmm
 __ZN3WTF12randomNumberEv
 __ZN3WTF13currentThreadEv
 __ZN3WTF13tryFastCallocEmm
+__ZN3WTF13tryFastMallocEm
 __ZN3WTF15ThreadCondition4waitERNS_5MutexE
 __ZN3WTF15ThreadCondition6signalEv
 __ZN3WTF15ThreadCondition9broadcastEv
 __ZN3WTF15ThreadCondition4waitERNS_5MutexE
 __ZN3WTF15ThreadCondition6signalEv
 __ZN3WTF15ThreadCondition9broadcastEv
@@ -295,6 +319,8 @@ __ZN3WTF15ThreadConditionC1Ev
 __ZN3WTF15ThreadConditionD1Ev
 __ZN3WTF16callOnMainThreadEPFvPvES0_
 __ZN3WTF16fastZeroedMallocEm
 __ZN3WTF15ThreadConditionD1Ev
 __ZN3WTF16callOnMainThreadEPFvPvES0_
 __ZN3WTF16fastZeroedMallocEm
+__ZN3WTF18dateToDaysFrom1970Eiii
+__ZN3WTF18monthFromDayInYearEib
 __ZN3WTF19initializeThreadingEv
 __ZN3WTF20fastMallocStatisticsEv
 __ZN3WTF21RefCountedLeakCounter16suppressMessagesEPKc
 __ZN3WTF19initializeThreadingEv
 __ZN3WTF20fastMallocStatisticsEv
 __ZN3WTF21RefCountedLeakCounter16suppressMessagesEPKc
@@ -303,9 +329,12 @@ __ZN3WTF21RefCountedLeakCounter9decrementEv
 __ZN3WTF21RefCountedLeakCounter9incrementEv
 __ZN3WTF21RefCountedLeakCounterC1EPKc
 __ZN3WTF21RefCountedLeakCounterD1Ev
 __ZN3WTF21RefCountedLeakCounter9incrementEv
 __ZN3WTF21RefCountedLeakCounterC1EPKc
 __ZN3WTF21RefCountedLeakCounterD1Ev
+__ZN3WTF23callOnMainThreadAndWaitEPFvPvES0_
+__ZN3WTF23dayInMonthFromDayInYearEib
 __ZN3WTF23waitForThreadCompletionEjPPv
 __ZN3WTF27releaseFastMallocFreeMemoryEv
 __ZN3WTF28setMainThreadCallbacksPausedEb
 __ZN3WTF23waitForThreadCompletionEjPPv
 __ZN3WTF27releaseFastMallocFreeMemoryEv
 __ZN3WTF28setMainThreadCallbacksPausedEb
+__ZN3WTF32doubleToStringInJavaScriptFormatEdPcPj
 __ZN3WTF36lockAtomicallyInitializedStaticMutexEv
 __ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
 __ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
 __ZN3WTF36lockAtomicallyInitializedStaticMutexEv
 __ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
 __ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
@@ -320,30 +349,41 @@ __ZN3WTF8Collator18setOrderLowerFirstEb
 __ZN3WTF8CollatorC1EPKc
 __ZN3WTF8CollatorD1Ev
 __ZN3WTF8fastFreeEPv
 __ZN3WTF8CollatorC1EPKc
 __ZN3WTF8CollatorD1Ev
 __ZN3WTF8fastFreeEPv
+__ZN3WTF8msToYearEd
+__ZN3WTF9dayInYearEdi
 __ZN3WTF9ByteArray6createEm
 __ZN3WTF9ByteArray6createEm
+__ZNK3JSC10JSFunction23isHostFunctionNonInlineEv
 __ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
 __ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
-__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE  
-__ZNK3JSC12DateInstance7getTimeERdRi
-__ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE
-__ZNK3JSC12StringObject8toStringEPNS_9ExecStateE
+__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
 __ZNK3JSC14JSGlobalObject14isDynamicScopeEv
 __ZNK3JSC14JSGlobalObject14isDynamicScopeEv
-__ZNK3JSC16FunctionBodyNode14isHostFunctionEv
 __ZNK3JSC16InternalFunction9classInfoEv
 __ZNK3JSC16JSVariableObject16isVariableObjectEv
 __ZNK3JSC16InternalFunction9classInfoEv
 __ZNK3JSC16JSVariableObject16isVariableObjectEv
-__ZNK3JSC16JSVariableObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
 __ZNK3JSC17DebuggerCallFrame10thisObjectEv
 __ZNK3JSC17DebuggerCallFrame12functionNameEv
 __ZNK3JSC17DebuggerCallFrame22calculatedFunctionNameEv
 __ZNK3JSC17DebuggerCallFrame4typeEv
 __ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_7JSValueE
 __ZNK3JSC17DebuggerCallFrame10thisObjectEv
 __ZNK3JSC17DebuggerCallFrame12functionNameEv
 __ZNK3JSC17DebuggerCallFrame22calculatedFunctionNameEv
 __ZNK3JSC17DebuggerCallFrame4typeEv
 __ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_7JSValueE
+__ZNK3JSC18PropertyDescriptor10enumerableEv
+__ZNK3JSC18PropertyDescriptor12configurableEv
+__ZNK3JSC18PropertyDescriptor16isDataDescriptorEv
+__ZNK3JSC18PropertyDescriptor20isAccessorDescriptorEv
+__ZNK3JSC18PropertyDescriptor6getterEv
+__ZNK3JSC18PropertyDescriptor6setterEv
+__ZNK3JSC18PropertyDescriptor8writableEv
 __ZNK3JSC4Heap10statisticsEv
 __ZNK3JSC4Heap10statisticsEv
+__ZNK3JSC4Heap11objectCountEv
+__ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
 __ZNK3JSC6JSCell14isGetterSetterEv
 __ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
 __ZNK3JSC6JSCell14isGetterSetterEv
+__ZNK3JSC6JSCell8toNumberEPNS_9ExecStateE
+__ZNK3JSC6JSCell8toObjectEPNS_9ExecStateE
+__ZNK3JSC6JSCell8toStringEPNS_9ExecStateE
 __ZNK3JSC6JSCell9classInfoEv
 __ZNK3JSC6JSCell9classInfoEv
-__ZNK3JSC6JSCell9getStringERNS_7UStringE
-__ZNK3JSC6JSCell9getStringEv
+__ZNK3JSC6JSCell9getStringEPNS_9ExecStateE
+__ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE
 __ZNK3JSC6JSCell9getUInt32ERj
 __ZNK3JSC6JSCell9getUInt32ERj
+__ZNK3JSC6JSCell9toBooleanEPNS_9ExecStateE
 __ZNK3JSC7ArgList8getSliceEiRS0_
 __ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateE
 __ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
 __ZNK3JSC7ArgList8getSliceEiRS0_
 __ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateE
 __ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
@@ -360,12 +400,12 @@ __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
 __ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
 __ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
-__ZNK3JSC8JSObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
 __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
 __ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
 __ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
 __ZNK3JSC8JSObject9classNameEv
 __ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
 __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
 __ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
 __ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
 __ZNK3JSC8JSObject9classNameEv
 __ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
+__ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE
 __ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
 __ZNK3JSC9HashTable11deleteTableEv
 __ZNK3WTF8Collator7collateEPKtmS2_m
 __ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
 __ZNK3JSC9HashTable11deleteTableEv
 __ZNK3WTF8Collator7collateEPKtmS2_m
@@ -374,7 +414,7 @@ __ZTVN3JSC14JSGlobalObjectE
 __ZTVN3JSC15JSWrapperObjectE
 __ZTVN3JSC16InternalFunctionE
 __ZTVN3JSC16JSVariableObjectE
 __ZTVN3JSC15JSWrapperObjectE
 __ZTVN3JSC16InternalFunctionE
 __ZTVN3JSC16JSVariableObjectE
-__ZTVN3JSC17JSAPIValueWrapperE
+__ZTVN3JSC8DebuggerE
 __ZTVN3JSC8JSObjectE
 __ZTVN3JSC8JSStringE
 _jscore_fastmalloc_introspection
 __ZTVN3JSC8JSObjectE
 __ZTVN3JSC8JSStringE
 _jscore_fastmalloc_introspection
diff --git a/JavaScriptCore.gyp/JavaScriptCore.gyp b/JavaScriptCore.gyp/JavaScriptCore.gyp
new file mode 100644 (file)
index 0000000..66f40e9
--- /dev/null
@@ -0,0 +1,191 @@
+#
+# Copyright (C) 2009 Google Inc. All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# 
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+{
+  'includes': [
+    # FIXME: Sense whether upstream or downstream build, and
+    # include the right features.gypi
+    '../../WebKit/chromium/features.gypi',
+    '../JavaScriptCore.gypi',
+  ],
+  'variables': {
+    # Location of the chromium src directory.
+    'conditions': [
+      ['inside_chromium_build==0', {
+        # Webkit is being built outside of the full chromium project.
+        'chromium_src_dir': '../../WebKit/chromium',
+      },{
+        # WebKit is checked out in src/chromium/third_party/WebKit
+        'chromium_src_dir': '../../../..',
+      }],
+    ],
+  },
+  'targets': [
+    {
+      # This target sets up defines and includes that are required by WTF and
+      # its dependents.
+      'target_name': 'wtf_config',
+      'type': 'none',
+      'msvs_guid': '2E2D3301-2EC4-4C0F-B889-87073B30F673',
+      'direct_dependent_settings': {
+        'defines': [
+          # Import features_defines from features.gypi
+          '<@(feature_defines)',
+          
+          # Turns on #if PLATFORM(CHROMIUM)
+          'BUILDING_CHROMIUM__=1',
+          # Controls wtf/FastMalloc
+          # FIXME: consider moving into config.h
+          'USE_SYSTEM_MALLOC=1',
+        ],
+        'conditions': [
+          ['OS=="win"', {
+            'defines': [
+              '__STD_C',
+              '_CRT_SECURE_NO_DEPRECATE',
+              '_SCL_SECURE_NO_DEPRECATE',
+              'CRASH=__debugbreak',
+            ],
+            'include_dirs': [
+              '../os-win32',
+            ],
+          }],
+          ['OS=="mac"', {
+            'defines': [
+              # Use USE_NEW_THEME on Mac.
+              'WTF_USE_NEW_THEME=1',
+            ],
+          }],
+          ['OS=="linux" or OS=="freebsd"', {
+            'defines': [
+              'WTF_USE_PTHREADS=1',
+            ],
+          }],
+        ],
+      }
+    },
+    {
+      'target_name': 'wtf',
+      'type': '<(library)',
+      'msvs_guid': 'AA8A5A85-592B-4357-BC60-E0E91E026AF6',
+      'dependencies': [
+        'wtf_config',
+        '<(chromium_src_dir)/third_party/icu/icu.gyp:icui18n',
+        '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
+      ],
+      'include_dirs': [
+        '../',
+        '../wtf',
+        '../wtf/unicode',
+      ],
+      'sources': [
+        '<@(javascriptcore_files)',
+      ],
+      'sources/': [
+        # First exclude everything ...
+        ['exclude', '../'],
+        # ... Then include what we want.
+        ['include', '../wtf/'],
+        # GLib/GTK, even though its name doesn't really indicate.
+        ['exclude', '/(gtk|glib)/.*\\.(cpp|h)$'],
+        ['exclude', '(Default|Gtk|Mac|None|Qt|Win|Wx)\\.(cpp|mm)$'],
+        ['exclude', 'wtf/CurrentTime\\.cpp$'],
+        ['exclude', 'wtf/TC.*\\.(cpp|h)$'],
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '../',
+          '../wtf',
+        ],
+      },
+      'export_dependent_settings': [
+        'wtf_config',
+        '<(chromium_src_dir)/third_party/icu/icu.gyp:icui18n',
+        '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
+      ],
+      'msvs_disabled_warnings': [4127, 4355, 4510, 4512, 4610, 4706],
+      'conditions': [
+        ['OS=="win"', {
+          'sources/': [
+            ['exclude', 'ThreadIdentifierDataPthreads\\.(h|cpp)$'],
+            ['exclude', 'ThreadingPthreads\\.cpp$'],
+            ['include', 'Thread(ing|Specific)Win\\.cpp$']
+          ],
+          'include_dirs!': [
+            '<(SHARED_INTERMEDIATE_DIR)/webkit',
+          ],
+        }],
+      ],
+    },
+    {
+      'target_name': 'pcre',
+      'type': '<(library)',
+      'dependencies': [
+        'wtf',
+      ],
+      'conditions': [
+        ['OS=="win"', {
+          'dependencies': ['<(chromium_src_dir)/build/win/system.gyp:cygwin'],
+        }],
+      ],
+      'msvs_guid': '49909552-0B0C-4C14-8CF6-DB8A2ADE0934',
+      'actions': [
+        {
+          'action_name': 'dftables',
+          'inputs': [
+            '../pcre/dftables',
+          ],
+          'outputs': [
+            '<(INTERMEDIATE_DIR)/chartables.c',
+          ],
+          'action': ['perl', '-w', '<@(_inputs)', '<@(_outputs)'],
+        },
+      ],
+      'include_dirs': [
+        '<(INTERMEDIATE_DIR)',
+      ],
+      'sources': [
+        '<@(javascriptcore_files)',
+      ],
+      'sources/': [
+        # First exclude everything ...
+        ['exclude', '../'],
+        # ... Then include what we want.
+        ['include', '../pcre/'],
+        # ucptable.cpp is #included by pcre_ucp_searchfunchs.cpp and is not
+        # intended to be compiled directly.
+        ['exclude', '../pcre/ucptable.cpp$'],
+      ],
+      'export_dependent_settings': [
+        'wtf',
+      ],
+    },
+  ], # targets
+}
index 2d69c7d6623be6cfd958f2814cf2d51eaf88a363..24577dabadf45568cae1a0f4cbb6a85313fce8ba 100644 (file)
@@ -1,7 +1,6 @@
 {
     'variables': {
         'javascriptcore_files': [
 {
     'variables': {
         'javascriptcore_files': [
-            'AllInOneFile.cpp',
             'API/APICast.h',
             'API/JavaScript.h',
             'API/JavaScriptCore.h',
             'API/APICast.h',
             'API/JavaScript.h',
             'API/JavaScriptCore.h',
@@ -19,6 +18,7 @@
             'API/JSClassRef.h',
             'API/JSContextRef.cpp',
             'API/JSContextRef.h',
             'API/JSClassRef.h',
             'API/JSContextRef.cpp',
             'API/JSContextRef.h',
+            'API/JSContextRefPrivate.h',
             'API/JSObjectRef.cpp',
             'API/JSObjectRef.h',
             'API/JSProfilerPrivate.cpp',
             'API/JSObjectRef.cpp',
             'API/JSObjectRef.h',
             'API/JSProfilerPrivate.cpp',
@@ -64,6 +64,7 @@
             'bytecode/StructureStubInfo.h',
             'bytecompiler/BytecodeGenerator.cpp',
             'bytecompiler/BytecodeGenerator.h',
             'bytecode/StructureStubInfo.h',
             'bytecompiler/BytecodeGenerator.cpp',
             'bytecompiler/BytecodeGenerator.h',
+            'bytecompiler/NodesCodegen.cpp',
             'bytecompiler/Label.h',
             'bytecompiler/LabelScope.h',
             'bytecompiler/RegisterID.h',
             'bytecompiler/Label.h',
             'bytecompiler/LabelScope.h',
             'bytecompiler/RegisterID.h',
             'pcre/ucpinternal.h',
             'pcre/ucptable.cpp',
             'profiler/CallIdentifier.h',
             'pcre/ucpinternal.h',
             'pcre/ucptable.cpp',
             'profiler/CallIdentifier.h',
-            'profiler/HeavyProfile.cpp',
-            'profiler/HeavyProfile.h',
             'profiler/Profile.cpp',
             'profiler/Profile.h',
             'profiler/ProfileGenerator.cpp',
             'profiler/Profile.cpp',
             'profiler/Profile.h',
             'profiler/ProfileGenerator.cpp',
             'profiler/Profiler.cpp',
             'profiler/Profiler.h',
             'profiler/ProfilerServer.h',
             'profiler/Profiler.cpp',
             'profiler/Profiler.h',
             'profiler/ProfilerServer.h',
-            'profiler/TreeProfile.cpp',
-            'profiler/TreeProfile.h',
             'runtime/ArgList.cpp',
             'runtime/ArgList.h',
             'runtime/Arguments.cpp',
             'runtime/ArgList.cpp',
             'runtime/ArgList.h',
             'runtime/Arguments.cpp',
             'runtime/DateConversion.h',
             'runtime/DateInstance.cpp',
             'runtime/DateInstance.h',
             'runtime/DateConversion.h',
             'runtime/DateInstance.cpp',
             'runtime/DateInstance.h',
+            'runtime/DateInstanceCache.h',
             'runtime/DatePrototype.cpp',
             'runtime/DatePrototype.h',
             'runtime/Error.cpp',
             'runtime/DatePrototype.cpp',
             'runtime/DatePrototype.h',
             'runtime/Error.cpp',
             'runtime/JSString.cpp',
             'runtime/JSString.h',
             'runtime/JSType.h',
             'runtime/JSString.cpp',
             'runtime/JSString.h',
             'runtime/JSType.h',
+            'runtime/JSTypeInfo.h',
             'runtime/JSValue.cpp',
             'runtime/JSValue.h',
             'runtime/JSVariableObject.cpp',
             'runtime/JSValue.cpp',
             'runtime/JSValue.h',
             'runtime/JSVariableObject.cpp',
             'runtime/LiteralParser.h',
             'runtime/Lookup.cpp',
             'runtime/Lookup.h',
             'runtime/LiteralParser.h',
             'runtime/Lookup.cpp',
             'runtime/Lookup.h',
+            'runtime/MarkStack.cpp',
+            'runtime/MarkStack.h',
+            'runtime/MarkStackWin.cpp',
             'runtime/MathObject.cpp',
             'runtime/MathObject.h',
             'runtime/NativeErrorConstructor.cpp',
             'runtime/MathObject.cpp',
             'runtime/MathObject.h',
             'runtime/NativeErrorConstructor.cpp',
             'runtime/ObjectPrototype.h',
             'runtime/Operations.cpp',
             'runtime/Operations.h',
             'runtime/ObjectPrototype.h',
             'runtime/Operations.cpp',
             'runtime/Operations.h',
+            'runtime/PropertyDescriptor.cpp',
+            'runtime/PropertyDescriptor.h',
             'runtime/PropertyMapHashTable.h',
             'runtime/PropertyNameArray.cpp',
             'runtime/PropertyNameArray.h',
             'runtime/PropertyMapHashTable.h',
             'runtime/PropertyNameArray.cpp',
             'runtime/PropertyNameArray.h',
             'runtime/TimeoutChecker.cpp',
             'runtime/TimeoutChecker.h',
             'runtime/Tracing.h',
             'runtime/TimeoutChecker.cpp',
             'runtime/TimeoutChecker.h',
             'runtime/Tracing.h',
-            'runtime/TypeInfo.h',
             'runtime/UString.cpp',
             'runtime/UString.h',
             'runtime/UString.cpp',
             'runtime/UString.h',
+            'runtime/WeakRandom.h',
             'wrec/CharacterClass.cpp',
             'wrec/CharacterClass.h',
             'wrec/CharacterClassConstructor.cpp',
             'wrec/CharacterClass.cpp',
             'wrec/CharacterClass.h',
             'wrec/CharacterClassConstructor.cpp',
             'wtf/FastMalloc.h',
             'wtf/Forward.h',
             'wtf/GetPtr.h',
             'wtf/FastMalloc.h',
             'wtf/Forward.h',
             'wtf/GetPtr.h',
-            'wtf/GOwnPtr.cpp',
-            'wtf/GOwnPtr.h',
+            'wtf/gtk/GOwnPtr.cpp',
+            'wtf/gtk/GOwnPtr.h',
             'wtf/gtk/MainThreadGtk.cpp',
             'wtf/gtk/ThreadingGtk.cpp',
             'wtf/HashCountedSet.h',
             'wtf/gtk/MainThreadGtk.cpp',
             'wtf/gtk/ThreadingGtk.cpp',
             'wtf/HashCountedSet.h',
             'wtf/PassRefPtr.h',
             'wtf/Platform.h',
             'wtf/PtrAndFlags.h',
             'wtf/PassRefPtr.h',
             'wtf/Platform.h',
             'wtf/PtrAndFlags.h',
-            'wtf/qt/MainThreadQt.cpp',
-            'wtf/qt/ThreadingQt.cpp',
             'wtf/RandomNumber.cpp',
             'wtf/RandomNumber.h',
             'wtf/RandomNumberSeed.h',
             'wtf/RandomNumber.cpp',
             'wtf/RandomNumber.h',
             'wtf/RandomNumberSeed.h',
             'wtf/SegmentedVector.h',
             'wtf/StdLibExtras.h',
             'wtf/StringExtras.h',
             'wtf/SegmentedVector.h',
             'wtf/StdLibExtras.h',
             'wtf/StringExtras.h',
+            'wtf/StringHashFunctions.h',
             'wtf/TCPackedCache.h',
             'wtf/TCPackedCache.h',
+            'wtf/qt/MainThreadQt.cpp',
+            'wtf/qt/ThreadingQt.cpp',
             'wtf/TCPageMap.h',
             'wtf/TCSpinLock.h',
             'wtf/TCSystemAlloc.cpp',
             'wtf/TCSystemAlloc.h',
             'wtf/TCPageMap.h',
             'wtf/TCSpinLock.h',
             'wtf/TCSystemAlloc.cpp',
             'wtf/TCSystemAlloc.h',
+            'wtf/ThreadIdentifierDataPthreads.cpp',
+            'wtf/ThreadIdentifierDataPthreads.h',
             'wtf/Threading.cpp',
             'wtf/Threading.h',
             'wtf/ThreadingNone.cpp',
             'wtf/Threading.cpp',
             'wtf/Threading.h',
             'wtf/ThreadingNone.cpp',
index 4cff982bcfbad61da96c0fcc320d0a9d9dff294f..f93c2ce049a5c9cf756b3c994c93d49d38862a29 100644 (file)
@@ -1,25 +1,27 @@
-// JavaScriptCore order file generated on Fri Feb 19 17:16:12 -0800 2010 by Andrew Turley (aturley@apple.com)
+// JavaScriptCore order file generated on Thu Apr 15 15:17:53 -0700 2010 by Mike Knippers (knippers@apple.com)
 // Scenario included SpringBoard launch/unlock with passcode, launching all apps, MobileSafari page loads,
 // keyboard usage and general app interaction.
 __ZN3WTF10fastMallocEm
 __ZN3WTF10fastMallocILb1EEEPvm
 __ZN3WTF20TCMalloc_ThreadCache10InitModuleEv
 // Scenario included SpringBoard launch/unlock with passcode, launching all apps, MobileSafari page loads,
 // keyboard usage and general app interaction.
 __ZN3WTF10fastMallocEm
 __ZN3WTF10fastMallocILb1EEEPvm
 __ZN3WTF20TCMalloc_ThreadCache10InitModuleEv
- stub helpers
 __ZN3WTFL15InitSizeClassesEv
 __Z20TCMalloc_SystemAllocmPmm
 __ZN3WTF20TCMalloc_ThreadCache22CreateCacheIfNecessaryEv
 __ZN3WTFL15InitSizeClassesEv
 __Z20TCMalloc_SystemAllocmPmm
 __ZN3WTF20TCMalloc_ThreadCache22CreateCacheIfNecessaryEv
+__ZN3WTF20TCMalloc_ThreadCache7NewHeapEP17_opaque_pthread_t
+__ZN3WTF20TCMalloc_ThreadCache14PickNextSampleEm
 __ZN3WTF25TCMalloc_Central_FreeList11RemoveRangeEPPvS2_Pi
 __ZN3WTF25TCMalloc_Central_FreeList18FetchFromSpansSafeEv
 __ZN3WTF25TCMalloc_Central_FreeList11RemoveRangeEPPvS2_Pi
 __ZN3WTF25TCMalloc_Central_FreeList18FetchFromSpansSafeEv
+__ZN3WTF17TCMalloc_PageHeap3NewEm
 __ZN3WTF17TCMalloc_PageHeap10AllocLargeEm
 __ZN3WTF17TCMalloc_PageHeap8GrowHeapEm
 __ZN3WTFL13MetaDataAllocEm
 __ZN3WTF17TCMalloc_PageHeap6DeleteEPNS_4SpanE
 __ZN3WTF17TCMalloc_PageHeap10AllocLargeEm
 __ZN3WTF17TCMalloc_PageHeap8GrowHeapEm
 __ZN3WTFL13MetaDataAllocEm
 __ZN3WTF17TCMalloc_PageHeap6DeleteEPNS_4SpanE
+__ZN3WTF17TCMalloc_PageHeap19IncrementalScavengeEm
+__Z22TCMalloc_SystemReleasePvm
+__ZN3WTF17TCMalloc_PageHeap5CarveEPNS_4SpanEmb
 __ZN3WTF16fastZeroedMallocEm
 __ZN3WTF8fastFreeEPv
 __ZN3WTF12isMainThreadEv
 __ZN3WTF16fastZeroedMallocEm
 __ZN3WTF8fastFreeEPv
 __ZN3WTF12isMainThreadEv
-__ZN3WTFL25identifierByPthreadHandleERKP17_opaque_pthread_t
-__ZN3WTFL35establishIdentifierForPthreadHandleERP17_opaque_pthread_t
-__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E6rehashEi
 __ZN3JSC19initializeThreadingEv
 __ZN3JSCL23initializeThreadingOnceEv
 __ZN3WTF19initializeThreadingEv
 __ZN3JSC19initializeThreadingEv
 __ZN3JSCL23initializeThreadingOnceEv
 __ZN3WTF19initializeThreadingEv
@@ -27,207 +29,292 @@ __ZN3WTF20initializeMainThreadEv
 __ZN3WTF5MutexC1Ev
 __ZN3WTF28initializeMainThreadPlatformEv
 __ZN3JSC17initializeUStringEv
 __ZN3WTF5MutexC1Ev
 __ZN3WTF28initializeMainThreadPlatformEv
 __ZN3JSC17initializeUStringEv
+__ZN3JSC12JSGlobalData10storeVPtrsEv
+__ZN3JSC9StructureC1ENS_7JSValueERKNS_8TypeInfoEj
+__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC7JSArrayD1Ev
+__ZN3JSC7JSArrayD2Ev
+__ZN3JSC9StructureD1Ev
+__ZN3JSC9StructureD2Ev
+__ZN3JSC11JSByteArray15createStructureENS_7JSValueE
+__ZN3JSC11JSByteArrayD1Ev
+__ZN3JSC8JSStringD1Ev
+__ZN3JSC8JSStringD2Ev
+__ZN3JSC10JSFunctionC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC10JSFunctionD1Ev
+__ZN3JSC10JSFunctionD2Ev
+__ZN3JSC18VPtrHackExecutableD0Ev
+__ZN3JSC16InternalFunctionD2Ev
 __ZN3WTF15initializeDatesEv
 __ZN3WTF15initializeDatesEv
+__ZN3WTF20equivalentYearForDSTEi
 __ZN3WTF11currentTimeEv
 __ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv
 __ZN3WTF36lockAtomicallyInitializedStaticMutexEv
 __ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
 __ZN3WTF11currentTimeEv
 __ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv
 __ZN3WTF36lockAtomicallyInitializedStaticMutexEv
 __ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
-__ZN3JSC8DebuggerC2Ev
 __ZN3WTF5Mutex4lockEv
 __ZN3WTF5Mutex6unlockEv
 __ZN3WTF6strtodEPKcPPc
 __ZN3WTF5Mutex4lockEv
 __ZN3WTF5Mutex6unlockEv
 __ZN3WTF6strtodEPKcPPc
-__ZN3JSC6JSLock12DropAllLocksC1Eb
+__ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
+__ZN3JSC6JSLock12DropAllLocksC2ENS_14JSLockBehaviorE
 __ZN3JSCL17createJSLockCountEv
 __ZN3JSC6JSLock12DropAllLocksD1Ev
 __ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
 __ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
 __ZN3JSCL17createJSLockCountEv
 __ZN3JSC6JSLock12DropAllLocksD1Ev
 __ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
 __ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
-__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
+__ZN3WTF20TCMalloc_ThreadCache21ReleaseToCentralCacheEmi
 __ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
 __ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
-__ZN3WTF5MutexD1Ev
-__ZN3WTF15ThreadConditionC1Ev
-__ZN3WTF12createThreadEPFPvS0_ES0_PKc
-__ZN3WTF20createThreadInternalEPFPvS0_ES0_PKc
-__ZN3WTFL16threadEntryPointEPv
-__ZN3WTF21setThreadNameInternalEPKc
-__ZN3WTF13currentThreadEv
-__ZN3WTF15ThreadCondition9broadcastEv
-__ZN3WTF15ThreadCondition6signalEv
-__ZN3WTF16callOnMainThreadEPFvPvES0_
-__ZN3WTF5DequeINS_19FunctionWithContextEE14expandCapacityEv
-__ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv
--[WTFMainThreadCaller call]
-__ZN3WTF31dispatchFunctionsFromMainThreadEv
-__ZN3WTF11fastReallocEPvm
-__ZN3WTF11fastReallocILb1EEEPvS1_m
-__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
-__ZL30calculateCompiledPatternLengthPKti24JSRegExpIgnoreCaseOptionR11CompileDataR9ErrorCode
-__ZL11checkEscapePPKtS0_P9ErrorCodeib
-__ZL13compileBranchiPiPPhPPKtS3_P9ErrorCodeS_S_R11CompileData
-__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
-__ZL5matchPKtPKhiR9MatchData
-__ZN3WTF25TCMalloc_Central_FreeList11ShrinkCacheEib
-__ZN3JSC7UStringC1EPKti
-__ZN3JSC7UStringC2EPKti
 __ZN3JSC12JSGlobalData12createLeakedEv
 __ZN3JSC9Structure18startIgnoringLeaksEv
 __ZN3JSC12JSGlobalData12createLeakedEv
 __ZN3JSC9Structure18startIgnoringLeaksEv
-__ZN3JSC7VPtrSetC2Ev
-__ZN3JSC9StructureC1ENS_7JSValueERKNS_8TypeInfoE
-__ZN3JSC7JSArrayC1EN3WTF10PassRefPtrINS_9StructureEEE
-__ZN3JSC7JSArrayD1Ev
-__ZN3JSC7JSArrayD2Ev
-__ZN3WTF10RefCountedIN3JSC9StructureEE5derefEv
-__ZN3JSC9StructureD1Ev
-__ZN3JSC9StructureD2Ev
-__ZN3JSC11JSByteArray15createStructureENS_7JSValueE
-__ZN3JSC11JSByteArrayD1Ev
-__ZN3JSC8JSStringD1Ev
-__ZN3JSC10JSFunctionD1Ev
-__ZN3JSC12JSGlobalDataC2EbRKNS_7VPtrSetE
+__ZN3JSC12JSGlobalDataC2Eb
 __ZN3JSC21createIdentifierTableEv
 __ZN3JSC17CommonIdentifiersC1EPNS_12JSGlobalDataE
 __ZN3JSC17CommonIdentifiersC2EPNS_12JSGlobalDataE
 __ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKc
 __ZN3JSC21createIdentifierTableEv
 __ZN3JSC17CommonIdentifiersC1EPNS_12JSGlobalDataE
 __ZN3JSC17CommonIdentifiersC2EPNS_12JSGlobalDataE
 __ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKc
-__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addIPKcNS1_17CStringTranslatorEEESt4pairINS_24HashTableIteratorAdapterINS_9HashTableIS4_S4_NS_17IdentityExtractorIS4_EES6_S8_S8_EES4_EEbERKT_
-__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7StrHashIS4_EENS_10HashTraitsIS4_EESA_E6rehashEi
-__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN3JSC7UString3RepEEEENS_18PairFirstExtractorIS9_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSF_IS8_EEEESG_E6rehashEi
+__ZNK3JSC11UStringImpl4hashEv
+__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN3JSC11UStringImplEEEENS_18PairFirstExtractorIS8_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSE_IS7_EEEESF_E4findIS2_NS_22IdentityHashTranslatorIS2_S8_SC_EEEENS_17HashTableIteratorIS2_S8_SA_SC_SH_SF_EERKT_
+__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN3JSC11UStringImplEEEENS_18PairFirstExtractorIS8_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSE_IS7_EEEESF_E6rehashEi
+__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN3JSC11UStringImplEEEENS_18PairFirstExtractorIS8_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSE_IS7_EEEESF_E3addIS2_S7_NS_17HashMapTranslatorIS8_SH_SC_EEEES3_INS_17HashTableIteratorIS2_S8_SA_SC_SH_SF_EEbERKT_RKT0_
+__ZN3WTF9HashTableIPN3JSC11UStringImplES3_NS_17IdentityExtractorIS3_EENS_7StrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC5equalEPKNS_11UStringImplES2_
+__ZN3WTF9HashTableIPN3JSC11UStringImplES3_NS_17IdentityExtractorIS3_EENS_7StrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_
 __ZN3JSC12SmallStringsC1Ev
 __ZN3JSC5LexerC1EPNS_12JSGlobalDataE
 __ZN3JSC12SmallStringsC1Ev
 __ZN3JSC5LexerC1EPNS_12JSGlobalDataE
-__ZN3JSC5LexerC2EPNS_12JSGlobalDataE
+__ZN3JSC11ParserArenaC1Ev
 __ZN3JSC11InterpreterC1Ev
 __ZN3JSC11InterpreterC2Ev
 __ZN3JSC11Interpreter14privateExecuteENS0_13ExecutionFlagEPNS_12RegisterFileEPNS_9ExecStateEPNS_7JSValueE
 __ZN3JSC11InterpreterC1Ev
 __ZN3JSC11InterpreterC2Ev
 __ZN3JSC11Interpreter14privateExecuteENS0_13ExecutionFlagEPNS_12RegisterFileEPNS_9ExecStateEPNS_7JSValueE
-__ZN3WTF9HashTableIPKvSt4pairIS2_N3JSC8OpcodeIDEENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS5_EEEESD_E6expandEv
+__ZN3WTF9HashTableIPKvSt4pairIS2_N3JSC8OpcodeIDEENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS5_EEEESD_E4findIS2_NS_22IdentityHashTranslatorIS2_S6_SA_EEEENS_17HashTableIteratorIS2_S6_S8_SA_SF_SD_EERKT_
+__ZN3WTF9HashTableIPKvSt4pairIS2_N3JSC8OpcodeIDEENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS5_EEEESD_E6rehashEi
+__ZN3WTF9HashTableIPKvSt4pairIS2_N3JSC8OpcodeIDEENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS5_EEEESD_E3addIS2_S5_NS_17HashMapTranslatorIS6_SF_SA_EEEES3_INS_17HashTableIteratorIS2_S6_S8_SA_SF_SD_EEbERKT_RKT0_
 __ZN3JSC14TimeoutCheckerC1Ev
 __ZN3JSC4HeapC1EPNS_12JSGlobalDataE
 __ZN3JSC14TimeoutCheckerC1Ev
 __ZN3JSC4HeapC1EPNS_12JSGlobalDataE
+__ZN3JSC4Heap13allocateBlockEv
+__ZN3WTF11fastReallocEPvm
+__ZN3WTF11fastReallocILb1EEEPvS1_m
+__ZN3JSC9MarkStack18initializePagesizeEv
+__ZN3JSC9MarkStack13allocateStackEm
 __ZN3JSC27startProfilerServerIfNeededEv
 +[ProfilerServer sharedProfileServer]
 -[ProfilerServer init]
 __ZN3JSC27startProfilerServerIfNeededEv
 +[ProfilerServer sharedProfileServer]
 -[ProfilerServer init]
+__ZN3JSC25setDefaultIdentifierTableEPNS_15IdentifierTableE
+__ZN3JSC29createIdentifierTableSpecificEv
+__ZN3JSCL37createIdentifierTableSpecificCallbackEv
+__ZN3JSC25setCurrentIdentifierTableEPNS_15IdentifierTableE
 __ZN3JSC9Structure17stopIgnoringLeaksEv
 __ZN3JSC9Structure17stopIgnoringLeaksEv
+__ZN3WTF5MutexD1Ev
+__ZN3WTF25TCMalloc_Central_FreeList14MakeCacheSpaceEv
+__ZN3WTF25TCMalloc_Central_FreeList11ShrinkCacheEib
+__ZN3WTF16callOnMainThreadEPFvPvES0_
+__ZN3WTF5DequeINS_19FunctionWithContextEE14expandCapacityEv
+__ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv
+-[WTFMainThreadCaller call]
+__ZN3WTF31dispatchFunctionsFromMainThreadEv
+__ZN3WTF15ThreadConditionC1Ev
+__ZN3WTF12createThreadEPFPvS0_ES0_PKc
+__ZN3WTF20createThreadInternalEPFPvS0_ES0_PKc
+__ZN3WTFL16threadEntryPointEPv
+__ZN3WTFL35establishIdentifierForPthreadHandleERKP17_opaque_pthread_t
+__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E6rehashEi
+__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E4findIjNS_22IdentityHashTranslatorIjS4_S8_EEEENS_17HashTableIteratorIjS4_S6_S8_SD_SB_EERKT_
+__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E3addIjS3_NS_17HashMapTranslatorIS4_SD_S8_EEEES1_INS_17HashTableIteratorIjS4_S6_S8_SD_SB_EEbERKT_RKT0_
+__ZN3WTF31initializeCurrentThreadInternalEPKc
+__ZN3WTF20ThreadIdentifierData10initializeEj
+__ZN3WTF20ThreadIdentifierData23initializeKeyOnceHelperEv
+__ZN3WTF13currentThreadEv
+__ZN3WTF20ThreadIdentifierData10identifierEv
+__ZN3WTF15ThreadCondition4waitERNS_5MutexE
+__ZN3WTF15ThreadCondition9broadcastEv
+__ZN3WTF15ThreadCondition6signalEv
+__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
+__ZL30calculateCompiledPatternLengthPKti24JSRegExpIgnoreCaseOptionR11CompileDataR9ErrorCode
+__ZL11checkEscapePPKtS0_P9ErrorCodeib
+__ZL13compileBranchiPiPPhPPKtS3_P9ErrorCodeS_S_R11CompileData
+__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
+__ZL5matchPKtPKhiR9MatchData
+__ZN3JSC7UStringC1EPKti
+__ZN3JSC7UStringC2EPKti
+__ZN3WTF13tryFastMallocEm
+__ZN3WTF10fastMallocILb0EEEPvm
+__ZN3JSC11UStringImpl12sharedBufferEv
 __ZN3JSC4Heap8allocateEm
 __ZN3JSC4Heap8allocateEm
-__ZN3JSCL13allocateBlockILNS_8HeapTypeE0EEEPNS_14CollectorBlockEv
-__ZN3JSC4Heap4heapENS_7JSValueE
+__ZN3JSC6JSCellD1Ev
 __ZN3JSC4Heap7protectENS_7JSValueE
 __ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi
 __ZN3JSC4Heap7protectENS_7JSValueE
 __ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi
+__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E4findIS3_NS_22IdentityHashTranslatorIS3_S5_S9_EEEENS_17HashTableIteratorIS3_S5_S7_S9_SE_SC_EERKT_
+__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E3addIS3_jNS_17HashMapTranslatorIS5_SE_S9_EEEES4_INS_17HashTableIteratorIS3_S5_S7_S9_SE_SC_EEbERKT_RKT0_
+__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E3addIS3_S5_NS_22IdentityHashTranslatorIS3_S5_S9_EEEES4_INS_17HashTableIteratorIS3_S5_S7_S9_SE_SC_EEbERKT_RKT0_
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
 __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
 __ZN3JSC14JSGlobalObject5resetENS_7JSValueE
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
 __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
 __ZN3JSC14JSGlobalObject5resetENS_7JSValueE
-__ZN3JSC4Heap12heapAllocateILNS_8HeapTypeE0EEEPvm
+__ZN3JSC17FunctionPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC17FunctionPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_10IdentifierE
 __ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE
 __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
 __ZN3JSC7UStringC1EPKc
 __ZN3JSCL9createRepEPKc
 __ZN3JSC8JSObject17putDirectInternalERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotEPNS_6JSCellE
 __ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
 __ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE
 __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
 __ZN3JSC7UStringC1EPKc
 __ZN3JSCL9createRepEPKc
 __ZN3JSC8JSObject17putDirectInternalERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotEPNS_6JSCellE
 __ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
-__ZN3JSC9Structure3getEPKNS_7UString3RepERjRPNS_6JSCellE
+__ZNK3JSC24StructureTransitionTable3getERKSt4pairIN3WTF6RefPtrINS_11UStringImplEEEjEPNS_6JSCellE
+__ZN3JSC9Structure3getEPKNS_11UStringImplERjRPNS_6JSCellE
 __ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
 __ZN3JSC9Structure3putERKNS_10IdentifierEjPNS_6JSCellE
 __ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
 __ZN3JSC9Structure3putERKNS_10IdentifierEjPNS_6JSCellE
+__ZN3JSC24StructureTransitionTable3addERKSt4pairIN3WTF6RefPtrINS_11UStringImplEEEjEPNS_9StructureEPNS_6JSCellE
 __ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEjPNS_6JSCellE
 __ZN3JSC17FunctionPrototype21addFunctionPropertiesEPNS_9ExecStateEPNS_9StructureEPPNS_17PrototypeFunctionES7_
 __ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEjPNS_6JSCellE
 __ZN3JSC17FunctionPrototype21addFunctionPropertiesEPNS_9ExecStateEPNS_9StructureEPPNS_17PrototypeFunctionES7_
-__ZN3JSC17PrototypeFunctionC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
+__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
+__ZN3JSC17PrototypeFunctionC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
 __ZN3JSC8JSObject34putDirectFunctionWithoutTransitionEPNS_9ExecStateEPNS_16InternalFunctionEj
 __ZN3JSC8JSObject34putDirectFunctionWithoutTransitionEPNS_9ExecStateEPNS_16InternalFunctionEj
-__ZN3JSC15ObjectPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC16InternalFunction4nameEPNS_9ExecStateE
+__ZN3JSC9Structure3getERKNS_10IdentifierE
+__ZN3JSC15ObjectPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC15ObjectPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
 __ZN3JSC9Structure26rehashPropertyMapHashTableEj
 __ZN3JSC9Structure26rehashPropertyMapHashTableEj
-__ZN3JSC15StringPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE
-__ZN3JSC16BooleanPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC15NumberPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
-__ZN3JSCL13allocateBlockILNS_8HeapTypeE1EEEPNS_14CollectorBlockEv
-__ZN3JSC15RegExpPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC14ErrorPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_
-__ZN3WTF6RefPtrIN3JSC7UString3RepEED1Ev
-__ZN3JSC20NativeErrorPrototypeC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEERKNS_7UStringES9_
-__ZN3JSC17ObjectConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15ObjectPrototypeE
-__ZN3JSC19FunctionConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_17FunctionPrototypeE
+__ZN3JSC8JSObject17createInheritorIDEv
+__ZN3JSC14ArrayPrototypeC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC7JSArrayC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC15StringPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC15StringPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC16BooleanPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC16BooleanPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC13BooleanObjectC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC15NumberPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC15NumberPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC12NumberObjectC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC13DatePrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC12DateInstanceC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC12nonInlineNaNEv
+__ZN3JSC15RegExpPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC15RegExpPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC14ErrorPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC14ErrorPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
+__ZN3JSC13ErrorInstanceC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC18jsNontrivialStringEPNS_12JSGlobalDataEPKc
+__ZN3JSC20NativeErrorPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7UStringES9_
+__ZN3JSC17ObjectConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15ObjectPrototypeEPS5_
+__ZN3JSC17ObjectConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15ObjectPrototypeEPS5_
+__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
+__ZN3JSC19FunctionConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_17FunctionPrototypeE
+__ZN3JSC19FunctionConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_17FunctionPrototypeE
 __ZNK3JSC16InternalFunction9classInfoEv
 __ZNK3JSC16InternalFunction9classInfoEv
-__ZN3JSC16ArrayConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_14ArrayPrototypeE
+__ZN3JSC16ArrayConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_14ArrayPrototypeEPS5_
+__ZN3JSC16ArrayConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_14ArrayPrototypeEPS5_
 __ZNK3JSC14ArrayPrototype9classInfoEv
 __ZNK3JSC14ArrayPrototype9classInfoEv
-__ZN3JSC17StringConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_PNS_15StringPrototypeE
+__ZN3JSC17StringConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_PNS_15StringPrototypeE
+__ZN3JSC17StringConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_PNS_15StringPrototypeE
 __ZNK3JSC15StringPrototype9classInfoEv
 __ZNK3JSC15StringPrototype9classInfoEv
-__ZN3JSC18BooleanConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_16BooleanPrototypeE
+__ZN3JSC18BooleanConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_16BooleanPrototypeE
+__ZN3JSC18BooleanConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_16BooleanPrototypeE
 __ZNK3JSC13BooleanObject9classInfoEv
 __ZNK3JSC13BooleanObject9classInfoEv
-__ZN3JSC17NumberConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15NumberPrototypeE
-__ZN3JSC15DateConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPS5_PNS_13DatePrototypeE
+__ZN3JSC17NumberConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15NumberPrototypeE
+__ZN3JSC17NumberConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15NumberPrototypeE
+__ZN3JSC15DateConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_PNS_13DatePrototypeE
+__ZN3JSC15DateConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_PNS_13DatePrototypeE
 __ZNK3JSC13DatePrototype9classInfoEv
 __ZNK3JSC13DatePrototype9classInfoEv
-__ZN3JSC17RegExpConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_15RegExpPrototypeE
-__ZN3JSC16ErrorConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_14ErrorPrototypeE
+__ZN3JSC17RegExpConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15RegExpPrototypeE
+__ZN3JSC17RegExpConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15RegExpPrototypeE
+__ZN3JSC16ErrorConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_14ErrorPrototypeE
+__ZN3JSC16ErrorConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_14ErrorPrototypeE
 __ZNK3JSC13ErrorInstance9classInfoEv
 __ZNK3JSC13ErrorInstance9classInfoEv
-__ZN3JSC22NativeErrorConstructorC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEPNS_20NativeErrorPrototypeE
-__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPNS_7UString3RepE
-__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addERKS4_
-__ZN3JSC10MathObjectC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEE
+__ZN3JSC22NativeErrorConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_20NativeErrorPrototypeE
+__ZN3JSC22NativeErrorConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_20NativeErrorPrototypeE
+__ZNK3JSC6JSCell9getStringEPNS_9ExecStateE
+__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_11UStringImplE
+__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPNS_11UStringImplE
+__ZN3WTF9HashTableIPN3JSC11UStringImplES3_NS_17IdentityExtractorIS3_EENS_7StrHashIS3_EENS_10HashTraitsIS3_EES9_E3addIS3_S3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEESt4pairINS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EEbERKT_RKT0_
+__ZN3JSC8JSObject23allocatePropertyStorageEmm
+__ZN3JSC10MathObjectC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC10MathObjectC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
 __ZN3JSC12SmallStrings24singleCharacterStringRepEh
 __ZN3JSC12SmallStrings24singleCharacterStringRepEh
-__ZN3JSC7JSValueC1EPNS_9ExecStateEd
-__ZN3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS2_16SymbolTableEntryENS2_17IdentifierRepHashENS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEE3addEPS4_RKS6_
-__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS2_16SymbolTableEntryEENS_18PairFirstExtractorIS8_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_26SymbolTableIndexHashTraitsEEESE_E6expandEv
+__ZN3JSC19SmallStringsStorageC2Ev
+__ZN3JSC14JSGlobalObject16addStaticGlobalsEPNS0_18GlobalPropertyInfoEi
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_NS2_16SymbolTableEntryEENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS4_EENS2_26SymbolTableIndexHashTraitsEEESD_E6rehashEi
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_NS2_16SymbolTableEntryEENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS4_EENS2_26SymbolTableIndexHashTraitsEEESD_E3addIPS3_S6_NS_29RefPtrHashMapRawKeyTranslatorISI_S7_SF_SA_EEEES5_INS_17HashTableIteratorIS4_S7_S9_SA_SF_SD_EEbERKT_RKT0_
+__ZN3JSC18GlobalEvalFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEEPNS_14JSGlobalObjectE
+__ZN3JSC14JSGlobalObject14resetPrototypeENS_7JSValueE
 __ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_7JSValueE
 __ZN3JSC9Structure17copyPropertyTableEv
 __ZN3JSC14JSGlobalObject10globalExecEv
 __ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_7JSValueE
 __ZN3JSC9Structure17copyPropertyTableEv
 __ZN3JSC14JSGlobalObject10globalExecEv
-__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
 __ZN3JSC4Heap9unprotectENS_7JSValueE
 __ZN3JSC4Heap9unprotectENS_7JSValueE
-__ZN3JSC6JSCellnwEmPNS_9ExecStateE
-__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_7UString3RepE
 __ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
 __ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
 __ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC7UString3Rep12sharedBufferEv
 __ZN3JSC14TimeoutChecker5resetEv
 __ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
 __ZN3JSC14TimeoutChecker5resetEv
 __ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
-__ZN3JSC6JSLock4lockEb
-__ZN3JSC6Parser5parseINS_11ProgramNodeEEEN3WTF10PassRefPtrIT_EEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE
+__ZN3JSC6JSLockC1EPNS_9ExecStateE
+__ZN3JSC17ProgramExecutable7compileEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser5parseINS_11ProgramNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPNS_8DebuggerEPNS_9ExecStateERKNS_10SourceCodeEPiPNS_7UStringE
 __ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
 __ZN3JSC7UStringaSEPKc
 __ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
 __ZN3JSC7UStringaSEPKc
+__ZN3JSC5Lexer7setCodeERKNS_10SourceCodeERNS_11ParserArenaE
 __Z10jscyyparsePv
 __ZN3JSC5Lexer3lexEPvS1_
 __Z10jscyyparsePv
 __ZN3JSC5Lexer3lexEPvS1_
+__ZN3JSC5Lexer19shiftLineTerminatorEv
 __ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKti
 __ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKti
-__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7StrHashIS4_EENS_10HashTraitsIS4_EEE3addINS1_11UCharBufferENS1_21UCharBufferTranslatorEEESt4pairINS_24HashTableIteratorAdapterINS_9HashTableIS4_S4_NS_17IdentityExtractorIS4_EES6_S8_S8_EES4_EEbERKT_
+__ZN3WTF9HashTableIPN3JSC11UStringImplES3_NS_17IdentityExtractorIS3_EENS_7StrHashIS3_EENS_10HashTraitsIS3_EES9_E18addPassingHashCodeINS1_11UCharBufferESC_NS_24HashSetTranslatorAdapterIS3_S9_SC_NS1_21UCharBufferTranslatorEEEEESt4pairINS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EEbERKT_RKT0_
+__ZN3WTF9HashTableIPN3JSC11UStringImplES3_NS_17IdentityExtractorIS3_EENS_7StrHashIS3_EENS_10HashTraitsIS3_EES9_E18addPassingHashCodeIPKcSD_NS_24HashSetTranslatorAdapterIS3_S9_SD_NS1_17CStringTranslatorEEEEESt4pairINS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EEbERKT_RKT0_
+__ZN3WTF9HashTableIPN3JSC11UStringImplES3_NS_17IdentityExtractorIS3_EENS_7StrHashIS3_EENS_10HashTraitsIS3_EES9_E20fullLookupForWritingINS1_11UCharBufferENS_24HashSetTranslatorAdapterIS3_S9_SC_NS1_21UCharBufferTranslatorEEEEESt4pairISG_IPS3_bEjERKT_
+__ZN3WTF9HashTableIPN3JSC11UStringImplES3_NS_17IdentityExtractorIS3_EENS_7StrHashIS3_EENS_10HashTraitsIS3_EES9_E20fullLookupForWritingIPKcNS_24HashSetTranslatorAdapterIS3_S9_SD_NS1_17CStringTranslatorEEEEESt4pairISH_IPS3_bEjERKT_
 __ZN3WTF15SegmentedVectorIN3JSC10IdentifierELm64EE6appendIS2_EEvRKT_
 __ZN3WTF15SegmentedVectorIN3JSC10IdentifierELm64EE6appendIS2_EEvRKT_
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataE
+__ZN3JSC11ParserArena14derefWithArenaEN3WTF10PassRefPtrINS_21ParserArenaRefCountedEEE
 __ZN3JSC5Lexer10sourceCodeEiii
 __ZN3JSC5Lexer10sourceCodeEiii
-__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeE
-__ZN3JSC20ParserArenaDeletablenwEmPNS_12JSGlobalDataE
-__ZN3WTF6VectorIPN3JSC20ParserArenaDeletableELm0EE14expandCapacityEm
-__ZN3WTF6VectorIPN3JSC12FuncDeclNodeELm0EE14expandCapacityEm
+__ZN3JSC11ParserArena20allocateFreeablePoolEv
+__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeERKNS_10IdentifierE
+__ZN3JSC18FunctionParametersC2EPNS_13ParameterNodeE
+__ZN3WTF6VectorIPN3JSC20ParserArenaDeletableELm0EE14expandCapacityEmPKS3_
+__ZN3JSC13StatementNode6setLocEii
+__ZN3WTF6VectorIPN3JSC16FunctionBodyNodeELm0EE14expandCapacityEmPKS3_
 __ZN3JSC14SourceElements6appendEPNS_13StatementNodeE
 __ZNK3JSC13StatementNode16isEmptyStatementEv
 __ZN3JSC14SourceElements6appendEPNS_13StatementNodeE
 __ZNK3JSC13StatementNode16isEmptyStatementEv
-__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEm
-__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEm
-__ZN3JSC5Lexer10scanRegExpEv
+__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEmPKS3_
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE15reserveCapacityEm
+__Z21mergeDeclarationListsIPN3JSC15ParserArenaDataIN3WTF6VectorISt4pairIPKNS0_10IdentifierEjELm0EEEEEET_SC_SC_
+__Z21mergeDeclarationListsIPN3JSC15ParserArenaDataIN3WTF6VectorIPNS0_16FunctionBodyNodeELm0EEEEEET_S9_S9_
+__ZN3JSC5Lexer10scanRegExpERPKNS_10IdentifierES4_t
 __ZN3WTF6VectorItLm0EE14expandCapacityEmPKt
 __ZN3WTF6VectorItLm0EE14expandCapacityEmPKt
-__ZN3JSC7UStringC2ERKN3WTF6VectorItLm0EEE
-__ZL20makeFunctionCallNodePvN3JSC8NodeInfoIPNS0_14ExpressionNodeEEENS1_IPNS0_13ArgumentsNodeEEEiii
+__ZL20makeFunctionCallNodePN3JSC12JSGlobalDataENS_8NodeInfoIPNS_14ExpressionNodeEEENS2_IPNS_13ArgumentsNodeEEEiii
 __ZNK3JSC15DotAccessorNode10isLocationEv
 __ZNK3JSC14ExpressionNode13isResolveNodeEv
 __ZNK3JSC14ExpressionNode21isBracketAccessorNodeEv
 __ZNK3JSC15DotAccessorNode10isLocationEv
 __ZNK3JSC14ExpressionNode13isResolveNodeEv
 __ZNK3JSC14ExpressionNode21isBracketAccessorNodeEv
-__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14shrinkCapacityEm
-__ZN3JSC5Lexer7record8Ei
-__ZL14makeAssignNodePvPN3JSC14ExpressionNodeENS0_8OperatorES2_bbiii
-__ZN3JSC7UString3Rep7destroyEv
+__ZN3JSC5Lexer10skipRegExpEv
+__ZL14makeAssignNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeENS_8OperatorES3_bbiii
 __ZNK3JSC11ResolveNode10isLocationEv
 __ZNK3JSC11ResolveNode13isResolveNodeEv
 __ZNK3JSC11ResolveNode10isLocationEv
 __ZNK3JSC11ResolveNode13isResolveNodeEv
-__ZL26appendToVarDeclarationListPvRPN3JSC15ParserArenaDataIN3WTF6VectorISt4pairINS0_10IdentifierEjELm0EEEEERKS5_j
-__ZN3WTF6VectorISt4pairIN3JSC10IdentifierEjELm0EE14expandCapacityEm
+__ZN3WTF6VectorISt4pairIPKN3JSC10IdentifierEjELm0EE14expandCapacityEmPKS6_
 __ZNK3JSC14ExpressionNode10isLocationEv
 __ZNK3JSC14ExpressionNode10isLocationEv
+__ZN3JSC6Parser16didFinishParsingEPNS_14SourceElementsEPNS_15ParserArenaDataIN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEEEPNS3_INS5_IPNS_16FunctionBodyNodeELm0EEEEEjii
 __ZN3JSC5Lexer5clearEv
 __ZN3JSC5Lexer5clearEv
-__ZN3JSC10Identifier6removeEPNS_7UString3RepE
-__ZN3WTF6VectorIN3JSC10IdentifierELm64EE14shrinkCapacityEm
-__ZN3JSC9ScopeNodeC2EPNS_12JSGlobalDataERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS9_IPNS_12FuncDeclNodeELm0EEEji
+__ZN3JSC11ProgramNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_IPNS_16FunctionBodyNodeELm0EEERKNS_10SourceCodeEji
+__ZN3JSC9ScopeNodeC2EPNS_12JSGlobalDataERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS9_IPNS_16FunctionBodyNodeELm0EEEji
+__ZN3JSC13ScopeNodeDataC2ERNS_11ParserArenaEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_IPNS_16FunctionBodyNodeELm0EEEi
 __ZN3JSC11ParserArena10removeLastEv
 __ZN3JSC11ParserArena5resetEv
 __ZN3JSC11ParserArena10removeLastEv
 __ZN3JSC11ParserArena5resetEv
-__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
-__ZN3JSC11Interpreter7executeEPNS_11ProgramNodeEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectEPNS_7JSValueE
-__ZN3JSC11ProgramNode16generateBytecodeEPNS_14ScopeChainNodeE
-__ZN3JSC9CodeBlockC2EPNS_9ScopeNodeENS_8CodeTypeEN3WTF10PassRefPtrINS_14SourceProviderEEEj
-__ZN3WTF9HashTableIPN3JSC16ProgramCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
-__ZN3JSC17BytecodeGeneratorC2EPNS_11ProgramNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_16ProgramCodeBlockE
-__ZN3WTF6VectorIN3JSC11InstructionELm0EE14expandCapacityEm
+__ZN3WTF15SegmentedVectorIN3JSC10IdentifierELm64EE5clearEv
+__ZN3WTF15SegmentedVectorIN3JSC10IdentifierELm64EE17deleteAllSegmentsEv
+__ZN3WTF6VectorIN3JSC10IdentifierELm64EE14shrinkCapacityEm
+__ZN3WTF6VectorINS_6RefPtrIN3JSC21ParserArenaRefCountedEEELm0EE14shrinkCapacityEm
+__ZN3JSC9CodeBlockC2EPNS_16ScriptExecutableENS_8CodeTypeEN3WTF10PassRefPtrINS_14SourceProviderEEEjPNS4_7HashMapINS4_6RefPtrINS_11UStringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS4_10HashTraitsISB_EENS_26SymbolTableIndexHashTraitsEEE
+__ZN3WTF9HashTableIPN3JSC15GlobalCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E3addIS3_S3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEESt4pairINS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EEbERKT_RKT0_
+__ZN3WTF9HashTableIPN3JSC15GlobalCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC17BytecodeGeneratorC1EPNS_11ProgramNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_11UStringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISD_EENS_26SymbolTableIndexHashTraitsEEEPNS_16ProgramCodeBlockE
+__ZN3JSC17BytecodeGeneratorC2EPNS_11ProgramNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_11UStringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISD_EENS_26SymbolTableIndexHashTraitsEEEPNS_16ProgramCodeBlockE
+__ZN3JSC17BytecodeGenerator10emitOpcodeENS_8OpcodeIDE
+__ZN3WTF15SegmentedVectorIN3JSC10RegisterIDELm32EE17ensureSegmentsForEm
+__ZN3WTF6VectorIN3JSC10RegisterIDELm32EE4growEm
+__ZN3JSC26BatchedTransitionOptimizerC2EPNS_8JSObjectE
 __ZN3JSC9Structure31toCacheableDictionaryTransitionEPS0_
 __ZN3JSC9Structure22toDictionaryTransitionEPS0_NS0_14DictionaryKindE
 __ZN3JSC9Structure31toCacheableDictionaryTransitionEPS0_
 __ZN3JSC9Structure22toDictionaryTransitionEPS0_NS0_14DictionaryKindE
+__ZN3JSC24StructureTransitionTable6removeERKSt4pairIN3WTF6RefPtrINS_11UStringImplEEEjEPNS_6JSCellE
 __ZN3JSC8JSObject12removeDirectERKNS_10IdentifierE
 __ZN3JSC9Structure24removePropertyTransitionEPS0_RKNS_10IdentifierERm
 __ZN3JSC9Structure6removeERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator12addGlobalVarERKNS_10IdentifierEbRPNS_10RegisterIDE
 __ZN3JSC8JSObject12removeDirectERKNS_10IdentifierE
 __ZN3JSC9Structure24removePropertyTransitionEPS0_RKNS_10IdentifierERm
 __ZN3JSC9Structure6removeERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator12addGlobalVarERKNS_10IdentifierEbRPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_12FuncDeclNodeE
-__ZN3JSC9CodeBlock25createRareDataIfNecessaryEv
-__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EE14expandCapacityEm
+__ZN3WTF15SegmentedVectorIN3JSC10RegisterIDELm32EE6appendIiEEvRKT_
+__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_16FunctionBodyNodeE
+__ZN3JSC9CodeBlock15addFunctionDeclEN3WTF17NonNullPassRefPtrINS_18FunctionExecutableEEE
 __ZN3JSC9Structure31removePropertyWithoutTransitionERKNS_10IdentifierE
 __ZN3JSC9Structure31removePropertyWithoutTransitionERKNS_10IdentifierE
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZNK3JSC7UString14toStrictUInt32EPb
 __ZN3JSC9Structure26flattenDictionaryStructureEPNS_8JSObjectE
 __ZN3JSCL30comparePropertyMapEntryIndicesEPKvS1_
 __ZNK3JSC7UString14toStrictUInt32EPb
 __ZN3JSC9Structure26flattenDictionaryStructureEPNS_8JSObjectE
 __ZN3JSCL30comparePropertyMapEntryIndicesEPKvS1_
@@ -235,37 +322,51 @@ __ZN3JSC17BytecodeGenerator8generateEv
 __ZN3JSC11ProgramNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13emitDebugHookENS_11DebugHookIDEii
 __ZN3JSC17BytecodeGenerator12newTemporaryEv
 __ZN3JSC11ProgramNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13emitDebugHookENS_11DebugHookIDEii
 __ZN3JSC17BytecodeGenerator12newTemporaryEv
-__ZN3JSC17BytecodeGenerator11newRegisterEv
+__ZN3WTF15SegmentedVectorIN3JSC10RegisterIDELm32EE6appendImEEvRKT_
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDENS_7JSValueE
 __ZN3JSC17BytecodeGenerator16addConstantValueENS_7JSValueE
 __ZN3JSC17BytecodeGenerator16addConstantValueENS_7JSValueE
-__ZN3WTF9HashTableIPvSt4pairIS1_jENS_18PairFirstExtractorIS3_EENS_7PtrHashIS1_EENS_14PairHashTraitsIN3JSC24EncodedJSValueHashTraitsENS_10HashTraitsIjEEEESA_E6expandEv
-__ZN3WTF6VectorIN3JSC8RegisterELm0EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC8RegisterELm0EE14expandCapacityEmPKS2_
 __ZN3JSC17BytecodeGenerator8emitMoveEPNS_10RegisterIDES2_
 __ZN3JSC17BytecodeGenerator8emitNodeEPNS_10RegisterIDEPNS_4NodeE
 __ZN3WTF6VectorIN3JSC8LineInfoELm0EE14expandCapacityEm
 __ZN3JSC12FuncDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator8newLabelEv
 __ZN3JSC17BytecodeGenerator8emitMoveEPNS_10RegisterIDES2_
 __ZN3JSC17BytecodeGenerator8emitNodeEPNS_10RegisterIDEPNS_4NodeE
 __ZN3WTF6VectorIN3JSC8LineInfoELm0EE14expandCapacityEm
 __ZN3JSC12FuncDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator8newLabelEv
-__ZN3JSC13LogicalOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF15SegmentedVectorIN3JSC5LabelELm32EE6appendIPNS1_9CodeBlockEEEvRKT_
+__ZNK3JSC13LogicalOpNode26hasConditionContextCodegenEv
+__ZN3JSC17BytecodeGenerator26emitNodeInConditionContextEPNS_14ExpressionNodeEPNS_5LabelES4_b
+__ZN3JSC13LogicalOpNode30emitBytecodeInConditionContextERNS_17BytecodeGeneratorEPNS_5LabelES4_b
+__ZNK3JSC14ExpressionNode26hasConditionContextCodegenEv
 __ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC14ExpressionNode6isNullEv
 __ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE
 __ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator11registerForERKNS_10IdentifierE
 __ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC14ExpressionNode6isNullEv
 __ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE
 __ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator11registerForERKNS_10IdentifierE
-__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator18emitExpressionInfoEjjj
+__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14expandCapacityEmPKS2_
 __ZN3JSC17BytecodeGenerator11emitGetByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator11emitGetByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
-__ZN3WTF6VectorIjLm0EE14expandCapacityEm
+__ZN3WTF6VectorIjLm0EE14expandCapacityEmPKj
 __ZN3JSC17BytecodeGenerator11addConstantERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator11addConstantERKNS_10IdentifierE
-__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_iENS_18PairFirstExtractorIS7_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS5_EENS2_17BytecodeGenerator28IdentifierMapIndexHashTraitsEEESD_E6rehashEi
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_iENS_18PairFirstExtractorIS6_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS4_EENS2_17BytecodeGenerator28IdentifierMapIndexHashTraitsEEESC_E6rehashEi
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_iENS_18PairFirstExtractorIS6_EENS2_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS4_EENS2_17BytecodeGenerator28IdentifierMapIndexHashTraitsEEESC_E3addIPS3_iNS_29RefPtrHashMapRawKeyTranslatorISI_S6_SF_S9_EEEES5_INS_17HashTableIteratorIS4_S6_S8_S9_SF_SC_EEbERKT_RKT0_
+__ZN3JSC9CodeBlock13addIdentifierERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE
 __ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
 __ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE
 __ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
+__ZNK3JSC14LogicalNotNode26hasConditionContextCodegenEv
 __ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitMethodCheckEv
+__ZN3JSC17BytecodeGenerator8emitCallEPNS_10RegisterIDES2_S2_PNS_13ArgumentsNodeEjjj
 __ZN3JSC17BytecodeGenerator8emitCallENS_8OpcodeIDEPNS_10RegisterIDES3_S3_PNS_13ArgumentsNodeEjjj
 __ZN3JSC16ArgumentListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC10RegExpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringES5_
 __ZN3JSC17BytecodeGenerator8emitCallENS_8OpcodeIDEPNS_10RegisterIDES3_S3_PNS_13ArgumentsNodeEjjj
 __ZN3JSC16ArgumentListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC10RegExpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringES5_
+__ZN3JSC6RegExpC2EPNS_12JSGlobalDataERKNS_7UStringES5_
+__ZNK3JSC7UString4findEti
 __ZN3JSC17BytecodeGenerator13emitNewRegExpEPNS_10RegisterIDEPNS_6RegExpE
 __ZN3JSC17BytecodeGenerator13emitNewRegExpEPNS_10RegisterIDEPNS_6RegExpE
+__ZN3JSC9CodeBlock9addRegExpEPNS_6RegExpE
+__ZN3JSC17BytecodeGenerator11emitUnaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_
 __ZN3JSC17BytecodeGenerator9emitLabelEPNS_5LabelE
 __ZN3JSC9BlockNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator9emitLabelEPNS_5LabelE
 __ZN3JSC9BlockNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
@@ -274,104 +375,106 @@ __ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRPNS_8JSO
 __ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE
 __ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE
+__ZN3JSC9CodeBlock15addFunctionExprEN3WTF17NonNullPassRefPtrINS_18FunctionExecutableEEE
 __ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
 __ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator15emitResolveBaseEPNS_10RegisterIDERKNS_10IdentifierE
 __ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
 __ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator15emitResolveBaseEPNS_10RegisterIDERKNS_10IdentifierE
 __ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13LogicalOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF15SegmentedVectorIN3JSC5LabelELm32EE10removeLastEv
 __ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
 __ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
 __ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitNewObjectEPNS_10RegisterIDE
 __ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC10StringNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDERKNS_10IdentifierE
 __ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC10StringNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDERKNS_10IdentifierE
-__ZN3WTF9HashTableIPN3JSC7UString3RepESt4pairIS4_PNS1_8JSStringEENS_18PairFirstExtractorIS8_EENS1_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS4_EENSD_IS7_EEEESE_E6expandEv
+__ZN3WTF9HashTableIPN3JSC11UStringImplESt4pairIS3_PNS1_8JSStringEENS_18PairFirstExtractorIS7_EENS1_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSC_IS6_EEEESD_E6rehashEi
+__ZN3WTF9HashTableIPN3JSC11UStringImplESt4pairIS3_PNS1_8JSStringEENS_18PairFirstExtractorIS7_EENS1_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSC_IS6_EEEESD_E3addIS3_S6_NS_17HashMapTranslatorIS7_SF_SA_EEEES4_INS_17HashTableIteratorIS3_S7_S9_SA_SF_SD_EEbERKT_RKT0_
+__ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE
+__ZN3JSC17BytecodeGenerator16emitUnaryNoDstOpENS_8OpcodeIDEPNS_10RegisterIDE
 __ZN3JSC12JSGlobalData22numericCompareFunctionEPNS_9ExecStateE
 __ZNK3JSC21UStringSourceProvider6lengthEv
 __ZN3JSC12JSGlobalData22numericCompareFunctionEPNS_9ExecStateE
 __ZNK3JSC21UStringSourceProvider6lengthEv
+__ZN3JSC18FunctionExecutable14fromGlobalCodeERKNS_10IdentifierEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE
 __ZNK3JSC21UStringSourceProvider4dataEv
 __ZNK3JSC21UStringSourceProvider4dataEv
-__ZN3JSC19extractFunctionBodyEPNS_11ProgramNodeE
+__ZNK3JSC9ScopeNode15singleStatementEv
 __ZNK3JSC17ExprStatementNode15isExprStatementEv
 __ZNK3JSC12FuncExprNode14isFuncExprNodeEv
 __ZNK3JSC17ExprStatementNode15isExprStatementEv
 __ZNK3JSC12FuncExprNode14isFuncExprNodeEv
-__ZN3JSC16FunctionBodyNode16generateBytecodeEPNS_14ScopeChainNodeE
-__ZN3JSC6Parser14reparseInPlaceEPNS_12JSGlobalDataEPNS_16FunctionBodyNodeE
-__ZL11makeSubNodePvPN3JSC14ExpressionNodeES2_b
+__ZThn12_N3JSC11ProgramNodeD0Ev
+__ZN3JSC9ScopeNodeD2Ev
+__ZN3JSC11ParserArenaD1Ev
+__ZN3JSC14SourceElementsD1Ev
+__ZThn12_N3JSC16FunctionBodyNodeD0Ev
+__ZN3WTF10RefCountedIN3JSC18FunctionParametersEE5derefEv
+__ZN3WTF15SegmentedVectorIN3JSC10IdentifierELm64EED1Ev
+__ZN3JSC18FunctionExecutable7compileEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser5parseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPNS_8DebuggerEPNS_9ExecStateERKNS_10SourceCodeEPiPNS_7UStringE
+__ZL11makeSubNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
 __ZN3JSC14ExpressionNode14stripUnaryPlusEv
 __ZNK3JSC14ExpressionNode8isNumberEv
 __ZN3JSC14ExpressionNode14stripUnaryPlusEv
 __ZNK3JSC14ExpressionNode8isNumberEv
-__ZN3JSC9CodeBlockC1EPNS_9ScopeNodeENS_8CodeTypeEN3WTF10PassRefPtrINS_14SourceProviderEEEj
-__ZN3JSC17BytecodeGeneratorC2EPNS_16FunctionBodyNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_9CodeBlockE
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_IPS0_Lm0EEERKNS_10SourceCodeEji
+__ZN3JSC16FunctionBodyNode13finishParsingEN3WTF10PassRefPtrINS_18FunctionParametersEEERKNS_10IdentifierE
+__ZN3JSC17BytecodeGeneratorC1EPNS_16FunctionBodyNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_11UStringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISD_EENS_26SymbolTableIndexHashTraitsEEEPNS_9CodeBlockE
+__ZN3JSC17BytecodeGeneratorC2EPNS_16FunctionBodyNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_11UStringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISD_EENS_26SymbolTableIndexHashTraitsEEEPNS_9CodeBlockE
 __ZN3JSC17BytecodeGenerator12addParameterERKNS_10IdentifierE
 __ZN3JSC16FunctionBodyNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC10ReturnNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC11ResolveNode6isPureERNS_17BytecodeGeneratorE
 __ZN3JSC17BytecodeGenerator12addParameterERKNS_10IdentifierE
 __ZN3JSC16FunctionBodyNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC10ReturnNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC11ResolveNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator7isLocalERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator10emitReturnEPNS_10RegisterIDE
 __ZNK3JSC9BlockNode7isBlockEv
 __ZNK3JSC10ReturnNode12isReturnNodeEv
 __ZN3JSC17BytecodeGenerator10emitReturnEPNS_10RegisterIDE
 __ZNK3JSC9BlockNode7isBlockEv
 __ZNK3JSC10ReturnNode12isReturnNodeEv
+__ZN3WTF6OwnPtrIN3JSC13ExceptionInfoEE5clearEv
 __ZN3JSC9CodeBlock11shrinkToFitEv
 __ZN3JSC9CodeBlock11shrinkToFitEv
-__ZN3WTF6VectorIN3JSC11InstructionELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC10IdentifierELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC10IdentifierELm0EE14shrinkCapacityEm
-__ZN3JSC11ParserArenaD1Ev
-__ZN3JSC11ResolveNodeD0Ev
-__ZN3JSC7SubNodeD0Ev
-__ZN3JSC14ExpressionNodeD2Ev
-__ZN3JSC10ReturnNodeD0Ev
-__ZN3JSC14SourceElementsD0Ev
-__ZN3JSC9BlockNodeD0Ev
+__ZN3WTF6VectorINS_6RefPtrIN3JSC18FunctionExecutableEEELm0EE14shrinkCapacityEm
+__ZN3JSC17BytecodeGeneratorD2Ev
+__ZN3WTF15SegmentedVectorIN3JSC10LabelScopeELm8EED1Ev
+__ZN3WTF15SegmentedVectorIN3JSC10LabelScopeELm8EE17deleteAllSegmentsEv
+__ZN3WTF15SegmentedVectorIN3JSC5LabelELm32EED1Ev
+__ZN3WTF15SegmentedVectorIN3JSC5LabelELm32EE17deleteAllSegmentsEv
+__ZN3WTF15SegmentedVectorIN3JSC10RegisterIDELm32EED1Ev
 __ZN3WTF6VectorIN3JSC11InstructionELm0EEaSERKS3_
 __ZN3WTF6VectorIN3JSC11InstructionELm0EEaSERKS3_
-__ZThn12_N3JSC11ProgramNodeD0Ev
-__ZN3JSC11ProgramNodeD0Ev
-__ZN3JSC13ParameterNodeD0Ev
-__ZN3JSC17ExprStatementNodeD0Ev
-__ZThn12_N3JSC12FuncExprNodeD0Ev
-__ZN3JSC12FuncExprNodeD0Ev
-__ZThn12_N3JSC16FunctionBodyNodeD0Ev
-__ZN3JSC16FunctionBodyNodeD0Ev
-__ZN3JSC9CodeBlockD1Ev
+__ZN3JSC18FunctionExecutableD0Ev
+__ZN3JSC17FunctionCodeBlockD0Ev
 __ZN3JSC9CodeBlockD2Ev
 __ZN3JSC9CodeBlockD2Ev
+__ZN3WTF6OwnPtrIN3JSC13ExceptionInfoEED1Ev
+__ZN3JSC11UStringImplD1Ev
+__ZN3JSC11UStringImplD2Ev
+__ZN3JSC10Identifier6removeEPNS_11UStringImplE
+__ZN3JSC22currentIdentifierTableEv
 __ZN3JSC21UStringSourceProviderD0Ev
 __ZN3JSC21UStringSourceProviderD0Ev
-__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorIN3JSC20GetByIdExceptionInfoELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorINS_6RefPtrIN3JSC12FuncDeclNodeEEELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorINS_6RefPtrIN3JSC6RegExpEEELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorINS_6RefPtrIN3JSC6RegExpEEELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm
-__ZN3JSC15ParserArenaDataIN3WTF6VectorIPNS_12FuncDeclNodeELm0EEEED0Ev
-__ZN3JSC15DotAccessorNodeD0Ev
-__ZN3JSC12NotEqualNodeD0Ev
-__ZN3JSC10RegExpNodeD0Ev
-__ZN3JSC16ArgumentListNodeD0Ev
-__ZN3JSC13ArgumentsNodeD0Ev
-__ZN3JSC19FunctionCallDotNodeD0Ev
-__ZN3JSC14LogicalNotNodeD0Ev
-__ZN3JSC13LogicalOpNodeD0Ev
-__ZN3JSC6IfNodeD0Ev
-__ZN3JSC13AssignDotNodeD0Ev
-__ZN3JSC17AssignResolveNodeD0Ev
-__ZN3JSC17ObjectLiteralNodeD0Ev
-__ZN3JSC15ParserArenaDataIN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEED0Ev
-__ZN3JSC16VarStatementNodeD0Ev
-__ZN3JSC21FunctionCallValueNodeD0Ev
-__ZN3JSC10StringNodeD0Ev
-__ZN3WTF14deleteOwnedPtrIN3JSC17BytecodeGeneratorEEEvPT_
+__ZN3JSC15ParserArenaDataIN3WTF6VectorIPNS_16FunctionBodyNodeELm0EEEED1Ev
+__ZN3JSC15ParserArenaDataIN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEED1Ev
+__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
+__ZN3JSC11Interpreter7executeEPNS_17ProgramExecutableEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectEPNS_7JSValueE
+__ZN3JSC12JSGlobalData14resetDateCacheEv
 __ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
 __ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
-__ZN3JSC12FuncDeclNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC18FunctionExecutable4makeEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_18FunctionExecutableEEEPNS_14ScopeChainNodeE
+__ZNK3JSC7JSValue3getEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC11Interpreter15tryCacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockEPNS_11InstructionENS_7JSValueERKNS_10IdentifierERKNS_12PropertySlotE
 __ZN3JSC7JSValue13equalSlowCaseEPNS_9ExecStateES0_S0_
 __ZN3JSC10JSFunction18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC11Interpreter15tryCacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockEPNS_11InstructionENS_7JSValueERKNS_10IdentifierERKNS_12PropertySlotE
 __ZN3JSC7JSValue13equalSlowCaseEPNS_9ExecStateES0_S0_
 __ZN3JSC10JSFunction18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC12FuncExprNode12makeFunctionEPNS_9ExecStateEPNS_14ScopeChainNodeE
-__ZN3JSC9Structure13hasTransitionEPNS_7UString3RepEj
+__ZN3JSC9Structure13hasTransitionEPNS_11UStringImplEj
 __ZN3JSC11Interpreter15tryCachePutByIDEPNS_9ExecStateEPNS_9CodeBlockEPNS_11InstructionENS_7JSValueERKNS_15PutPropertySlotE
 __ZN3JSC11Interpreter13resolveGlobalEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
 __ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
 __ZN3JSC10JSFunction11getCallDataERNS_8CallDataE
 __ZN3JSC11Interpreter15tryCachePutByIDEPNS_9ExecStateEPNS_9CodeBlockEPNS_11InstructionENS_7JSValueERKNS_15PutPropertySlotE
 __ZN3JSC11Interpreter13resolveGlobalEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
 __ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
 __ZN3JSC10JSFunction11getCallDataERNS_8CallDataE
-__ZL17combineCommaNodesPvPN3JSC14ExpressionNodeES2_
-__ZL15makePostfixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
+__ZL15makePostfixNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeENS_8OperatorEiii
 __ZNK3JSC18EmptyStatementNode16isEmptyStatementEv
 __ZNK3JSC18EmptyStatementNode16isEmptyStatementEv
+__ZNK3JSC10NumberNode8isNumberEv
+__ZN3JSC17BytecodeGenerator6addVarERKNS_10IdentifierEbRPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15isLocalConstantERKNS_10IdentifierE
 __ZNK3JSC16JSVariableObject16isVariableObjectEv
 __ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_7JSValueE
 __ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
 __ZNK3JSC16JSVariableObject16isVariableObjectEv
 __ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_7JSValueE
 __ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
+__ZN3WTF15SegmentedVectorIN3JSC10LabelScopeELm8EE6appendIS2_EEvRKT_
 __ZN3JSC10NumberNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEd
 __ZN3JSC10NumberNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEd
-__ZN3WTF9HashTableIdSt4pairIdN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E6expandEv
 __ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
 __ZN3JSC15ConditionalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZL14compileBracketiPiPPhPPKtS3_P9ErrorCodeiS_S_R11CompileData
 __ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
 __ZN3JSC15ConditionalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZL14compileBracketiPiPPhPPKtS3_P9ErrorCodeiS_S_R11CompileData
@@ -380,393 +483,470 @@ __ZN3JSC9BreakNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator11breakTargetERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator14emitJumpScopesEPNS_5LabelEi
 __ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator11breakTargetERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator14emitJumpScopesEPNS_5LabelEi
 __ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator10emitPreIncEPNS_10RegisterIDE
 __ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
 __ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
+__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE
 __ZN3JSC16PropertyListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC16PropertyListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC10NumberNodeD0Ev
-__ZN3JSC19BracketAccessorNodeD0Ev
-__ZN3JSC18PostfixResolveNodeD0Ev
-__ZN3JSC15ConditionalNodeD0Ev
-__ZN3JSC9BreakNodeD0Ev
-__ZN3JSC18EmptyStatementNodeD0Ev
-__ZN3JSC7ForNodeD0Ev
-__ZN3JSC12PropertyNodeD0Ev
-__ZN3JSC16PropertyListNodeD0Ev
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC17PrototypeFunction11getCallDataERNS_8CallDataE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC17PrototypeFunction11getCallDataERNS_8CallDataE
-__ZNK3JSC8JSString8toStringEPNS_9ExecStateE
+__ZNK3JSC7JSValue3getEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZNK3JSC12PropertySlot8getValueEPNS_9ExecStateEj
 __ZN3JSC7UString4fromEj
 __ZN3JSC7UString4fromEj
-__ZN3JSC7UString3Rep6createEPtiN3WTF10PassRefPtrINS3_21CrossThreadRefCountedINS3_16OwnFastMallocPtrItEEEEEE
 __ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE
 __ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE
-__ZN3JSC12RegExpObjectC1EN3WTF10PassRefPtrINS_9StructureEEENS2_INS_6RegExpEEE
+__ZN3JSC12RegExpObjectC1EN3WTF17NonNullPassRefPtrINS_9StructureEEENS2_INS_6RegExpEEE
 __ZN3JSC12RegExpObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC12RegExpObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC18getStaticValueSlotINS_12RegExpObjectENS_8JSObjectEEEbPNS_9ExecStateEPKNS_9HashTableEPT_RKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC6JSCell8isObjectEPKNS_9ClassInfoE
 __ZNK3JSC12RegExpObject9classInfoEv
 __ZNK3JSC12RegExpObject9classInfoEv
+__ZN3JSC12RegExpObject4testEPNS_9ExecStateERKNS_7ArgListE
 __ZN3JSC12RegExpObject5matchEPNS_9ExecStateERKNS_7ArgListE
 __ZNK3JSC7JSValue8toStringEPNS_9ExecStateE
 __ZN3JSC17RegExpConstructor12performMatchEPNS_6RegExpERKNS_7UStringEiRiS6_PPi
 __ZN3JSC6RegExp5matchERKNS_7UStringEiPN3WTF6VectorIiLm32EEE
 __ZN3JSC17RegExpConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC12RegExpObject5matchEPNS_9ExecStateERKNS_7ArgListE
 __ZNK3JSC7JSValue8toStringEPNS_9ExecStateE
 __ZN3JSC17RegExpConstructor12performMatchEPNS_6RegExpERKNS_7UStringEiRiS6_PPi
 __ZN3JSC6RegExp5matchERKNS_7UStringEiPN3WTF6VectorIiLm32EEE
 __ZN3JSC17RegExpConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC18getStaticValueSlotINS_17RegExpConstructorENS_16InternalFunctionEEEbPNS_9ExecStateEPKNS_9HashTableEPT_RKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSCL24regExpConstructorDollar1EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
 __ZN3JSC11jsSubstringEPNS_12JSGlobalDataERKNS_7UStringEjj
 __ZN3JSCL24regExpConstructorDollar1EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
 __ZN3JSC11jsSubstringEPNS_12JSGlobalDataERKNS_7UStringEjj
-__ZN3JSC20constructEmptyObjectEPNS_9ExecStateE
-__ZN3WTF7HashMapISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjES1_IPNS3_9StructureES9_ENS3_28StructureTransitionTableHashENS3_34StructureTransitionTableHashTraitsENS_10HashTraitsISA_EEE3addERKS7_RKSA_
-__ZN3WTF9HashTableISt4pairINS_6RefPtrIN3JSC7UString3RepEEEjES1_IS7_S1_IPNS3_9StructureES9_EENS_18PairFirstExtractorISB_EENS3_28StructureTransitionTableHashENS_14PairHashTraitsINS3_34StructureTransitionTableHashTraitsENS_10HashTraitsISA_EEEESG_E6rehashEi
-__ZN3WTF7HashSetINS_6RefPtrIN3JSC7UString3RepEEENS2_17IdentifierRepHashENS_10HashTraitsIS5_EEE3addERKS5_
-__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEES5_NS_17IdentityExtractorIS5_EENS2_17IdentifierRepHashENS_10HashTraitsIS5_EESA_E6rehashEi
+__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC8JSString12toThisStringEPNS_9ExecStateE
+__ZNK3JSC7UString4findERKS0_i
+__ZN3JSC7JSValue11strictEqualEPNS_9ExecStateES0_S0_
+__ZN3JSC24StructureTransitionTable21reifySingleTransitionEv
+__ZN3WTF9HashTableISt4pairINS_6RefPtrIN3JSC11UStringImplEEEjES1_IS6_S1_IPNS3_9StructureES8_EENS_18PairFirstExtractorISA_EENS3_28StructureTransitionTableHashENS_14PairHashTraitsINS3_34StructureTransitionTableHashTraitsENS_10HashTraitsIS9_EEEESF_E4findIS6_NS_22IdentityHashTranslatorIS6_SA_SD_EEEENS_17HashTableIteratorIS6_SA_SC_SD_SI_SF_EERKT_
+__ZN3WTF9HashTableISt4pairINS_6RefPtrIN3JSC11UStringImplEEEjES1_IS6_S1_IPNS3_9StructureES8_EENS_18PairFirstExtractorISA_EENS3_28StructureTransitionTableHashENS_14PairHashTraitsINS3_34StructureTransitionTableHashTraitsENS_10HashTraitsIS9_EEEESF_E6rehashEi
+__ZN3WTF9HashTableISt4pairINS_6RefPtrIN3JSC11UStringImplEEEjES1_IS6_S1_IPNS3_9StructureES8_EENS_18PairFirstExtractorISA_EENS3_28StructureTransitionTableHashENS_14PairHashTraitsINS3_34StructureTransitionTableHashTraitsENS_10HashTraitsIS9_EEEESF_E3addIS6_S9_NS_17HashMapTranslatorISA_SI_SD_EEEES1_INS_17HashTableIteratorIS6_SA_SC_SD_SI_SF_EEbERKT_RKT0_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEES4_NS_17IdentityExtractorIS4_EENS2_17IdentifierRepHashENS_10HashTraitsIS4_EES9_E6rehashEi
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEES4_NS_17IdentityExtractorIS4_EENS2_17IdentifierRepHashENS_10HashTraitsIS4_EES9_E3addIS4_S4_NS_22IdentityHashTranslatorIS4_S4_S7_EEEESt4pairINS_17HashTableIteratorIS4_S4_S6_S7_S9_S9_EEbERKT_RKT0_
 __ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEb
 __ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC13StatementNode12isReturnNodeEv
 __ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC13StatementNode12isReturnNodeEv
-__ZN3JSC11BooleanNodeD0Ev
-__ZN3JSC10IfElseNodeD0Ev
-__ZN3JSC12JSActivationC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_16FunctionBodyNodeEEE
-__ZN3JSC12JSActivationC2EPNS_9ExecStateEN3WTF10PassRefPtrINS_16FunctionBodyNodeEEE
+__ZN3JSC12JSActivationC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_18FunctionExecutableEEE
 __ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
-__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12JSActivation13copyRegistersEPNS_9ArgumentsE
 __ZN3JSCL20stringProtoFuncMatchEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL20stringProtoFuncMatchEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC8JSString12toThisStringEPNS_9ExecStateE
 __ZNK3JSC6JSCell9classInfoEv
 __ZNK3JSC6JSCell9classInfoEv
+__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringE
+__ZN3JSC6RegExpD1Ev
 __Z12jsRegExpFreeP8JSRegExp
 __Z12jsRegExpFreeP8JSRegExp
-__ZL11makeAddNodePvPN3JSC14ExpressionNodeES2_b
+__ZL11makeAddNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
 __ZNK3JSC19BracketAccessorNode10isLocationEv
 __ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv
 __ZNK3JSC19BracketAccessorNode10isLocationEv
 __ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv
-__ZL14makePrefixNodePvPN3JSC14ExpressionNodeENS0_8OperatorEiii
+__ZL14makePrefixNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeENS_8OperatorEiii
 __ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC9EqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE
-__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
-__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
 __ZNK3JSC14ExpressionNode5isAddEv
 __ZNK3JSC12JSActivation14isDynamicScopeEv
 __ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE
 __ZNK3JSC14ExpressionNode5isAddEv
 __ZNK3JSC12JSActivation14isDynamicScopeEv
 __ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
 __ZN3JSC23FunctionCallResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC7AddNode5isAddEv
 __ZN3JSC12BinaryOpNode10emitStrcatERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_PNS_21ReadModifyResolveNodeE
 __ZNK3JSC10StringNode8isStringEv
 __ZNK3JSC14ExpressionNode8isStringEv
 __ZN3JSC23FunctionCallResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC7AddNode5isAddEv
 __ZN3JSC12BinaryOpNode10emitStrcatERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_PNS_21ReadModifyResolveNodeE
 __ZNK3JSC10StringNode8isStringEv
 __ZNK3JSC14ExpressionNode8isStringEv
+__ZN3JSC17BytecodeGenerator15emitToPrimitiveEPNS_10RegisterIDES2_
 __ZN3JSC17BytecodeGenerator10emitStrcatEPNS_10RegisterIDES2_i
 __ZN3JSC17AssignBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_
 __ZN3JSC17BytecodeGenerator10emitStrcatEPNS_10RegisterIDES2_i
 __ZN3JSC17AssignBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC9EqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC10StringNode6isPureERNS_17BytecodeGeneratorE
 __ZN3JSC17TypeOfResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC10StringNode6isPureERNS_17BytecodeGeneratorE
 __ZN3JSC17TypeOfResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSCeqERKNS_7UStringEPKc
 __ZN3JSC9ArrayNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator12emitNewArrayEPNS_10RegisterIDEPNS_11ElementNodeE
 __ZN3JSC13PrefixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC9ArrayNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator12emitNewArrayEPNS_10RegisterIDEPNS_11ElementNodeE
 __ZN3JSC13PrefixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC9ThrowNodeD0Ev
-__ZN3JSC9EqualNodeD0Ev
-__ZN3JSC7AddNodeD0Ev
-__ZN3JSC15StrictEqualNodeD0Ev
-__ZN3JSC23FunctionCallResolveNodeD0Ev
-__ZN3JSC17AssignBracketNodeD0Ev
-__ZN3JSC17TypeOfResolveNodeD0Ev
-__ZN3JSC9ArrayNodeD0Ev
-__ZN3JSC13PrefixDotNodeD0Ev
-__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7UString4findERKS0_i
-__ZN3JSC11concatenateEPNS_7UString3RepES2_
+__ZN3JSC8JSStringC2EPNS_12JSGlobalDataEjPS0_S3_
+__ZN3JSC9ArgumentsC2EPNS_9ExecStateE
 __ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC17BytecodeGenerator16emitPutScopedVarEmiPNS_10RegisterIDENS_7JSValueE
 __ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC17BytecodeGenerator16emitPutScopedVarEmiPNS_10RegisterIDENS_7JSValueE
+__ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE
 __ZNK3JSC7UString8toUInt32EPbb
 __ZNK3JSC7UString8toDoubleEbb
 __ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZNK3JSC7UString8toUInt32EPbb
 __ZNK3JSC7UString8toDoubleEbb
 __ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC15ObjectPrototype18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
-__ZN3JSC7UString3Rep15reserveCapacityEi
-__ZN3WTF11fastReallocILb0EEEPvS1_m
-__ZN3JSC7UString6appendERKS0_
+__ZN3JSC8JSString40appendValueInConstructAndIncrementLengthEPNS_9ExecStateERjNS_7JSValueE
 __ZN3JSC16jsIsFunctionTypeENS_7JSValueE
 __ZNK3JSC9CodeBlock13refStructuresEPNS_11InstructionE
 __ZN3JSC16jsIsFunctionTypeENS_7JSValueE
 __ZNK3JSC9CodeBlock13refStructuresEPNS_11InstructionE
+__ZN3JSC23normalizePrototypeChainEPNS_9ExecStateENS_7JSValueES2_RKNS_10IdentifierERm
+__ZNK3JSC9Structure14prototypeChainEPNS_9ExecStateE
 __ZN3JSC14StructureChainC1EPNS_9StructureE
 __ZN3JSC14StructureChainC2EPNS_9StructureE
 __ZN3JSC14StructureChainC1EPNS_9StructureE
 __ZN3JSC14StructureChainC2EPNS_9StructureE
-__ZNK3JSC14StructureChain11isCacheableEv
+__ZN3JSC17ProgramExecutableD0Ev
+__ZN3JSC16ProgramCodeBlockD0Ev
+__ZN3JSC15GlobalCodeBlockD2Ev
+__ZN3WTF9HashTableIPN3JSC15GlobalCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_
 __ZNK3JSC9CodeBlock15derefStructuresEPNS_11InstructionE
 __ZNK3JSC9CodeBlock15derefStructuresEPNS_11InstructionE
-__ZN3JSC6RegExpD1Ev
-__ZThn12_N3JSC12FuncDeclNodeD0Ev
-__ZN3JSC12FuncDeclNodeD0Ev
-__ZNK3JSC10NumberNode8isNumberEv
-__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEm
+__ZN3JSC9CodeBlock8RareDataD2Ev
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_NS1_INS2_14EvalExecutableEEEENS_18PairFirstExtractorIS8_EENS_7StrHashIS4_EENS_14PairHashTraitsINS_10HashTraitsIS4_EENSE_IS7_EEEESF_E15deallocateTableEPS8_i
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_NS1_INS2_14EvalExecutableEEEENS_18PairFirstExtractorIS8_EENS_7StrHashIS4_EENS_14PairHashTraitsINS_10HashTraitsIS4_EENSE_IS7_EEEESF_E4findIS4_NS_22IdentityHashTranslatorIS4_S8_SC_EEEENS_17HashTableIteratorIS4_S8_SA_SC_SH_SF_EERKT_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_NS1_INS2_14EvalExecutableEEEENS_18PairFirstExtractorIS8_EENS_7StrHashIS4_EENS_14PairHashTraitsINS_10HashTraitsIS4_EENSE_IS7_EEEESF_E6rehashEi
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_NS1_INS2_14EvalExecutableEEEENS_18PairFirstExtractorIS8_EENS_7StrHashIS4_EENS_14PairHashTraitsINS_10HashTraitsIS4_EENSE_IS7_EEEESF_E3addIPS3_S7_NS_29RefPtrHashMapRawKeyTranslatorISK_S8_SH_SC_EEEES5_INS_17HashTableIteratorIS4_S8_SA_SC_SH_SF_EEbERKT_RKT0_
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EED1Ev
+__ZN3WTF6VectorIPvLm0EE14expandCapacityEmPKS1_
+__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEmPKS4_
 __ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC8WithNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13emitPushScopeEPNS_10RegisterIDE
 __ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC8WithNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13emitPushScopeEPNS_10RegisterIDE
-__ZN3WTF6VectorIN3JSC18ControlFlowContextELm0EE14expandCapacityEm
-__ZL17bracketIsAnchoredPKh
+__ZN3WTF6VectorIN3JSC18ControlFlowContextELm0EE14expandCapacityEmPKS2_
+__ZN3JSC17BytecodeGenerator12emitPopScopeEv
+__ZL33bracketFindFirstAssertedCharacterPKhb
 __ZL32branchFindFirstAssertedCharacterPKhb
 __ZL20branchNeedsLineStartPKhjj
 __ZL32branchFindFirstAssertedCharacterPKhb
 __ZL20branchNeedsLineStartPKhjj
+__ZN3WTF9HashTableIxSt4pairIxjENS_18PairFirstExtractorIS2_EENS_7IntHashIxEENS_14PairHashTraitsIN3JSC24EncodedJSValueHashTraitsENS_10HashTraitsIjEEEES9_E4findIxNS_22IdentityHashTranslatorIxS2_S6_EEEENS_17HashTableIteratorIxS2_S4_S6_SC_S9_EERKT_
+__ZN3WTF9HashTableIxSt4pairIxjENS_18PairFirstExtractorIS2_EENS_7IntHashIxEENS_14PairHashTraitsIN3JSC24EncodedJSValueHashTraitsENS_10HashTraitsIjEEEES9_E6rehashEi
+__ZN3WTF9HashTableIxSt4pairIxjENS_18PairFirstExtractorIS2_EENS_7IntHashIxEENS_14PairHashTraitsIN3JSC24EncodedJSValueHashTraitsENS_10HashTraitsIjEEEES9_E3addIxjNS_17HashMapTranslatorIS2_SC_S6_EEEES1_INS_17HashTableIteratorIxS2_S4_S6_SC_S9_EEbERKT_RKT0_
 __ZN3JSC23CallFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator25emitJumpIfNotFunctionCallEPNS_10RegisterIDEPNS_5LabelE
 __ZN3JSC21ThrowableBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_PNS_13ArgumentsNodeEjjj
 __ZN3JSC23CallFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator25emitJumpIfNotFunctionCallEPNS_10RegisterIDEPNS_5LabelE
 __ZN3JSC21ThrowableBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_PNS_13ArgumentsNodeEjjj
-__ZN3WTF6VectorIN3JSC20GetByIdExceptionInfoELm0EE14expandCapacityEm
-__ZN3JSC11GreaterNodeD0Ev
-__ZN3JSC18NotStrictEqualNodeD0Ev
-__ZN3JSC8WithNodeD0Ev
-__ZN3JSC11ElementNodeD0Ev
-__ZN3JSC23CallFunctionCallDotNodeD0Ev
-__ZN3JSC6InNodeD0Ev
-__ZN3JSC11NewExprNodeD0Ev
+__ZN3WTF6VectorIN3JSC20GetByIdExceptionInfoELm0EE14expandCapacityEmPKS2_
+__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
+__ZNK3JSC17RegExpConstructor14arrayOfMatchesEPNS_9ExecStateE
 __ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE
 __ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE
-__ZN3JSC7JSArrayC2EN3WTF10PassRefPtrINS_9StructureEEEj
+__ZN3JSC7JSArrayC2EN3WTF17NonNullPassRefPtrINS_9StructureEEEj
+__ZN3JSC7JSArray19setLazyCreationDataEPv
 __ZNK3JSC7UString10getCStringERN3WTF6VectorIcLm32EEE
 __ZNK3JSC7UString10getCStringERN3WTF6VectorIcLm32EEE
+__ZN3JSC9ForInNodeC2EPNS_12JSGlobalDataERKNS_10IdentifierEPNS_14ExpressionNodeES7_PNS_13StatementNodeEiii
+__ZN3JSC20ParserArenaDeletablenwEmPNS_12JSGlobalDataE
 __ZN3JSC9ForInNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC9ForInNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator20emitNextPropertyNameEPNS_10RegisterIDES2_PNS_5LabelE
-__ZN3JSC9ForInNodeD0Ev
-__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
-__ZN3JSC9Structure26getEnumerablePropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayEPNS_8JSObjectE
-__ZN3JSC9Structure35getEnumerableNamesFromPropertyTableERNS_17PropertyNameArrayE
-__ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE
-__ZN3JSC22JSPropertyNameIterator10invalidateEv
+__ZN3JSC17BytecodeGenerator20emitGetPropertyNamesEPNS_10RegisterIDES2_S2_S2_PNS_5LabelE
+__ZN3JSC17BytecodeGenerator18pushOptimisedForInEPNS_10RegisterIDES2_S2_S2_
+__ZN3WTF6VectorIN3JSC12ForInContextELm0EE14expandCapacityEmPKS2_
+__ZN3WTF11VectorMoverILb0EN3JSC12ForInContextEE4moveEPKS2_S5_PS2_
+__ZN3JSC17BytecodeGenerator20emitNextPropertyNameEPNS_10RegisterIDES2_S2_S2_S2_PNS_5LabelE
+__ZN3JSC22JSPropertyNameIterator6createEPNS_9ExecStateEPNS_8JSObjectE
+__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC8JSObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC9Structure16getPropertyNamesERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC17PropertyNameArray14addKnownUniqueEPNS_11UStringImplE
+__ZN3WTF10RefCountedIN3JSC21PropertyNameArrayDataEE5derefEv
+__ZN3JSC22JSPropertyNameIterator3getEPNS_9ExecStateEPNS_8JSObjectEm
+__ZN3JSC9Structure27despecifyFunctionTransitionEPS0_RKNS_10IdentifierE
+__ZN3JSC9Structure17despecifyFunctionERKNS_10IdentifierE
 __ZN3JSC9Structure22materializePropertyMapEv
 __ZNK3JSC14ExpressionNode11isCommaNodeEv
 __ZN3JSC9Structure22materializePropertyMapEv
 __ZNK3JSC14ExpressionNode11isCommaNodeEv
+__ZN3JSC9CommaNodeC1EPNS_12JSGlobalDataEPNS_14ExpressionNodeES4_
 __ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC8ThisNodeD0Ev
-__ZN3JSC9CommaNodeD0Ev
+__ZN3JSC9CommaNodeD1Ev
 __ZN3JSC9WhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC9WhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC9WhileNodeD0Ev
+__ZN3JSC17BytecodeGenerator11emitPostDecEPNS_10RegisterIDES2_
 __ZN3JSC16ArrayConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL29constructWithArrayConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSCL27constructArrayWithSizeQuirkEPNS_9ExecStateERKNS_7ArgListE
 __ZN3JSC16ArrayConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL29constructWithArrayConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSCL27constructArrayWithSizeQuirkEPNS_9ExecStateERKNS_7ArgListE
-__ZNK3JSC7JSValue8toUInt32EPNS_9ExecStateE
-__ZN3JSC7JSArray3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEEj
 __ZN3JSC17RegExpConstructor3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC17RegExpConstructor3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC9lookupPutINS_17RegExpConstructorEEEbPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEPKNS_9HashTableEPT_
 __ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC8NullNodeD0Ev
-__ZN3JSC8LessNodeD0Ev
 __ZN3JSC6JSCell11getCallDataERNS_8CallDataE
 __ZN3JSC10JSFunction3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC6JSCell11getCallDataERNS_8CallDataE
 __ZN3JSC10JSFunction3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC7JSArrayC2EN3WTF10PassRefPtrINS_9StructureEEERKNS_7ArgListE
+__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7ArgListE
 __ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF6VectorIN3JSC10IdentifierELm20EE14expandCapacityEm
+__ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC7JSArray20increaseVectorLengthEj
+__ZN3WTF14tryFastReallocEPvm
+__ZN3WTF11fastReallocILb0EEEPvS1_m
+__ZN3WTF6VectorIN3JSC10IdentifierELm20EE15reserveCapacityEm
 __ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC9Structure27despecifyFunctionTransitionEPS0_RKNS_10IdentifierE
 __ZN3JSC11Interpreter7resolveEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
 __ZN3JSC11Interpreter14uncacheGetByIDEPNS_9CodeBlockEPNS_11InstructionE
 __ZN3JSC7JSArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC17NumberConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC11Interpreter7resolveEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
 __ZN3JSC11Interpreter14uncacheGetByIDEPNS_9CodeBlockEPNS_11InstructionE
 __ZN3JSC7JSArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC17NumberConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC18getStaticValueSlotINS_17NumberConstructorENS_16InternalFunctionEEEbPNS_9ExecStateEPKNS_9HashTableEPT_RKNS_10IdentifierERNS_12PropertySlotE
 __ZNK3JSC8JSString12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC8JSString12toThisObjectEPNS_9ExecStateE
+__ZN3JSC12StringObjectC1EN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_8JSStringE
 __ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12StringObject14toThisJSStringEPNS_9ExecStateE
+__ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE
+__ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
+__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
+__ZNK3JSC8JSObject11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZNK3JSC8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
+__ZN3JSCL23stringProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12StringObject9classInfoEv
 __ZN3JSC8JSString14toThisJSStringEPNS_9ExecStateE
 __ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC8JSString14toThisJSStringEPNS_9ExecStateE
 __ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC19constructEmptyArrayEPNS_9ExecStateE
+__ZN3JSC7JSArray3putEPNS_9ExecStateEjNS_7JSValueE
 __ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_7JSValueE
 __ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_
 __ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_7JSValueE
 __ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_
-__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEm
-__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERNS_10IdentifierES2_
-__ZN3JSC7TryNodeD0Ev
+__ZN3JSC9CodeBlock19addExceptionHandlerERKNS_11HandlerInfoE
+__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEmPKS2_
+__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERKNS_10IdentifierES2_
 __ZNK3JSC9CommaNode11isCommaNodeEv
 __ZNK3JSC9CommaNode11isCommaNodeEv
+__ZN3JSC9CommaNode6appendEPNS_14ExpressionNodeE
 __ZN3JSCL21arrayProtoFuncForEachEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL21arrayProtoFuncForEachEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC11Interpreter20prepareForRepeatCallEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_10JSFunctionEiPNS_14ScopeChainNodeEPNS_7JSValueE
+__ZN3JSC11Interpreter20prepareForRepeatCallEPNS_18FunctionExecutableEPNS_9ExecStateEPNS_10JSFunctionEiPNS_14ScopeChainNodeEPNS_7JSValueE
+__ZN3JSC17BytecodeGenerator11emitPostIncEPNS_10RegisterIDES2_
 __ZN3JSC11Interpreter7executeERNS_16CallFrameClosureEPNS_7JSValueE
 __ZN3JSC10MathObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC11Interpreter7executeERNS_16CallFrameClosureEPNS_7JSValueE
 __ZN3JSC10MathObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC11Interpreter13endRepeatCallERNS_16CallFrameClosureE\r
-__ZN3JSC8JSObject23allocatePropertyStorageEmm
+__ZN3JSC21getStaticFunctionSlotINS_8JSObjectEEEbPNS_9ExecStateEPKNS_9HashTableEPS1_RKNS_10IdentifierERNS_12PropertySlotE
+__ZNK3JSC21UntypedPtrAndBitfieldanEm
+__ZN3JSC11Interpreter13endRepeatCallERNS_16CallFrameClosureE
+__ZN3JSC14LogicalNotNode30emitBytecodeInConditionContextERNS_17BytecodeGeneratorEPNS_5LabelES4_b
 __ZN3JSCL19arrayProtoFuncShiftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSCL19arrayProtoFuncShiftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSCL11getPropertyEPNS_9ExecStateEPNS_8JSObjectEj
 __ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateEj
 __ZN3JSC7JSArray9setLengthEj
 __ZN3JSC10JSFunction16getConstructDataERNS_13ConstructDataE
 __ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateEj
 __ZN3JSC7JSArray9setLengthEj
 __ZN3JSC10JSFunction16getConstructDataERNS_13ConstructDataE
-__ZN3JSC8JSObject17createInheritorIDEv
 __ZN3JSCL25functionProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZNK3JSC10JSFunction9classInfoEv
 __ZN3JSCL25functionProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZNK3JSC10JSFunction9classInfoEv
-__ZN3JSCplERKNS_7UStringES2_
-__ZN3JSC7UString6appendEPKc
+__ZNK3JSC7UStringixEi
+__ZNK3JSC18FunctionExecutable11paramStringEv
+__ZN3WTF6VectorItLm64EE6appendIcEEvPKT_m
+__ZN3JSC13StringBuilder7releaseEv
+__ZN3JSC10makeStringIPKcNS_7UStringES2_S3_S2_S3_EES3_T_T0_T1_T2_T3_T4_
 __ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC7JSArray16lazyCreationDataEv
 __ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE
 __ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE
+__ZN3JSC24RegExpConstructorPrivateD1Ev
 __ZN3JSCL19arrayProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
 __ZN3JSC24ApplyFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC14ExpressionNode13isSimpleArrayEv
 __ZN3JSC17BytecodeGenerator26emitJumpIfNotFunctionApplyEPNS_10RegisterIDEPNS_5LabelE
 __ZN3JSCL19arrayProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
 __ZN3JSC24ApplyFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC14ExpressionNode13isSimpleArrayEv
 __ZN3JSC17BytecodeGenerator26emitJumpIfNotFunctionApplyEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC17BytecodeGenerator22willResolveToArgumentsERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator15emitLoadVarargsEPNS_10RegisterIDES2_
 __ZN3JSC17BytecodeGenerator15emitCallVarargsEPNS_10RegisterIDES2_S2_S2_jjj
 __ZN3JSC17BytecodeGenerator15emitCallVarargsEPNS_10RegisterIDES2_S2_S2_jjj
-__ZN3JSC24ApplyFunctionCallDotNodeD0Ev
 __ZNK3JSC7JSArray9classInfoEv
 __ZN3JSC7JSArray15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
 __ZNK3JSC7UString30spliceSubstringsWithSeparatorsEPKNS0_5RangeEiPKS0_i
 __ZNK3JSC7JSArray9classInfoEv
 __ZN3JSC7JSArray15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
 __ZNK3JSC7UString30spliceSubstringsWithSeparatorsEPKNS0_5RangeEiPKS0_i
-__ZN3JSC7UString17expandPreCapacityEi
+__ZN3JSC4Heap15recordExtraCostEm
+__ZNK3JSC8JSObject3getEPNS_9ExecStateEj
+__ZN3JSC4Heap9markRootsEv
+__ZN3JSC4Heap30markStackObjectsConservativelyERNS_9MarkStackE
+__ZN3JSC4Heap31markCurrentThreadConservativelyERNS_9MarkStackE
+__ZN3JSC4Heap39markCurrentThreadConservativelyInternalERNS_9MarkStackE
+__ZN3JSC4Heap18markConservativelyERNS_9MarkStackEPvS3_
+__ZN3JSC9MarkStack5drainEv
+__ZN3JSC9MarkStack12markChildrenEPNS_6JSCellE
+__ZN3JSC8JSObject12markChildrenERNS_9MarkStackE
+__ZN3JSC14JSGlobalObject12markChildrenERNS_9MarkStackE
+__ZN3JSC9CodeBlock13markAggregateERNS_9MarkStackE
+__ZN3JSC18FunctionExecutable13markAggregateERNS_9MarkStackE
+__ZN3JSC10JSFunction12markChildrenERNS_9MarkStackE
+__ZN3JSC7JSArray12markChildrenERNS_9MarkStackE
+__ZN3JSC7JSArray18markChildrenDirectERNS_9MarkStackE
+__ZN3JSC15JSWrapperObject12markChildrenERNS_9MarkStackE
+__ZN3JSC18GlobalEvalFunction12markChildrenERNS_9MarkStackE
+__ZN3JSC12JSActivation12markChildrenERNS_9MarkStackE
+__ZN3JSC9Arguments12markChildrenERNS_9MarkStackE
+__ZN3JSCL12markIfNeededERNS_9MarkStackENS_7JSValueE
+__ZN3JSC4Heap20markProtectedObjectsERNS_9MarkStackE
+__ZN3JSC22JSPropertyNameIterator12markChildrenERNS_9MarkStackE
+__ZN3JSC12SmallStrings12markChildrenERNS_9MarkStackE
+__ZN3JSC9MarkStack7compactEv
+__ZN3JSC4Heap12resizeBlocksEv
+__ZNK3JSC4Heap11markedCellsEmm
+__ZN3JSC17PrototypeFunctionD1Ev
+__ZN3JSC12RegExpObjectD1Ev
+__ZN3JSC12JSActivationD1Ev
+__ZN3JSC12JSActivation16JSActivationDataD1Ev
+__ZN3JSC16JSVariableObjectD2Ev
+__ZN3JSC9ArgumentsD1Ev
+__ZN3JSC9ArgumentsD2Ev
+__ZN3JSC18RegExpMatchesArrayD1Ev
+__ZN3JSC8JSObjectD1Ev
+__ZN3JSC12StringObjectD1Ev
+__ZN3JSC15JSWrapperObjectD2Ev
 __ZN3JSCL19isInvalidParamForInEPNS_9ExecStateEPNS_9CodeBlockEPKNS_11InstructionENS_7JSValueERS7_
 __ZN3JSCL19isInvalidParamForInEPNS_9ExecStateEPNS_9CodeBlockEPKNS_11InstructionENS_7JSValueERS7_
-__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC15IdentifierArena21makeNumericIdentifierEPNS_12JSGlobalDataEd
 __ZN3JSC7UString4fromEd
 __ZN3JSC7UString4fromEd
+__ZN3WTF32doubleToStringInJavaScriptFormatEdPcPj
+__ZN3JSC7UStringC1EPKci
 __ZN3WTF4dtoaEPcdiPiS1_PS0_
 __ZN3JSC12ContinueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator14continueTargetERKNS_10IdentifierE
 __ZN3JSC13DeleteDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator14emitDeleteByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
 __ZN3WTF4dtoaEPcdiPiS1_PS0_
 __ZN3JSC12ContinueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator14continueTargetERKNS_10IdentifierE
 __ZN3JSC13DeleteDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator14emitDeleteByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
-__ZN3JSC12ContinueNodeD0Ev
-__ZN3JSC13DeleteDotNodeD0Ev
 __ZN3JSC10JSFunction14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZNK3JSC7ArgList8getSliceEiRS0_
 __ZN3JSC10JSFunction14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZNK3JSC7ArgList8getSliceEiRS0_
-__ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE
-__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
-__ZNK3JSC8JSObject11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
-__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSC9Arguments13copyRegistersEv
 __ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF7HashSetIPN3JSC8JSObjectENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E3addIS3_S3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEESt4pairINS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EEbERKT_RKT0_
 __ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
 __ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC14NumericStrings3addEi
 __ZN3JSC7UString4fromEi
 __ZN3JSC7UString4fromEi
-__ZN3WTF6VectorItLm256EE6appendItEEvPKT_m
+__ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_
 __ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12nonInlineNaNEv
 __ZN3JSC16ErrorConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL29constructWithErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSC14constructErrorEPNS_9ExecStateERKNS_7ArgListE
 __ZN3JSC16ErrorConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL29constructWithErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSC14constructErrorEPNS_9ExecStateERKNS_7ArgListE
-__ZN3WTF21CrossThreadRefCountedINS_16OwnFastMallocPtrItEEE5derefEv
-__ZN3WTF6VectorINS_6RefPtrIN3JSC10RegisterIDEEELm16EE14expandCapacityEm
-__ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
-__ZN3JSC11Interpreter7executeEPNS_16FunctionBodyNodeEPNS_9ExecStateEPNS_10JSFunctionEPNS_8JSObjectERKNS_7ArgListEPNS_14ScopeChainNodeEPNS_7JSValueE
+__ZN3JSC13ErrorInstanceC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC10JSFunction4callEPNS_9ExecStateENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11Interpreter7executeEPNS_18FunctionExecutableEPNS_9ExecStateEPNS_10JSFunctionEPNS_8JSObjectERKNS_7ArgListEPNS_14ScopeChainNodeEPNS_7JSValueE
+__ZN3WTF10RefCountedIN3JSC14StructureChainEE5derefEv
 __ZN3JSC15TypeOfValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC15TypeOfValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC15TypeOfValueNodeD0Ev
 __ZN3JSC20jsTypeStringForValueEPNS_9ExecStateENS_7JSValueE
 __ZN3JSC20jsTypeStringForValueEPNS_9ExecStateENS_7JSValueE
-__ZN3JSC10Identifier5equalEPKNS_7UString3RepEPKc
-__ZN3JSC13UnaryPlusNodeD0Ev
 __ZNK3JSC8JSString8toNumberEPNS_9ExecStateE
 __ZNK3JSC8JSString8toNumberEPNS_9ExecStateE
+__ZNK3JSC7UString8toDoubleEv
 __ZN3JSC17BytecodeGenerator19emitResolveWithBaseEPNS_10RegisterIDES2_RKNS_10IdentifierE
 __ZN3JSC17RegExpConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL30constructWithRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSC15constructRegExpEPNS_9ExecStateERKNS_7ArgListE
 __ZN3JSC18globalFuncUnescapeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC17BytecodeGenerator19emitResolveWithBaseEPNS_10RegisterIDES2_RKNS_10IdentifierE
 __ZN3JSC17RegExpConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL30constructWithRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSC15constructRegExpEPNS_9ExecStateERKNS_7ArgListE
 __ZN3JSC18globalFuncUnescapeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC7UString6appendEt
-__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm8EE14expandCapacityEm
+__ZN3WTF6VectorItLm64EE14expandCapacityEmPKt
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm8EE14expandCapacityEmPKS3_
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
 __ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
-__ZN3JSC4Heap7collectEv
-__ZN3JSC4Heap30markStackObjectsConservativelyEv
-__ZN3JSC4Heap31markCurrentThreadConservativelyEv
-__ZN3JSC4Heap39markCurrentThreadConservativelyInternalEv
-__ZN3JSC4Heap18markConservativelyEPvS1_
-__ZN3JSC14JSGlobalObject4markEv
-__ZN3JSC8JSObject4markEv
-__ZN3JSC6JSCell4markEv
-__ZN3JSC10JSFunction4markEv
-__ZN3JSC16FunctionBodyNode4markEv
-__ZN3JSC9CodeBlock4markEv
-__ZN3JSC12JSActivation4markEv
-__ZN3JSC9Arguments4markEv
-__ZN3JSC7JSArray4markEv
-__ZN3JSC15JSWrapperObject4markEv
-__ZN3JSC18GlobalEvalFunction4markEv
-__ZN3JSC19JSStaticScopeObject4markEv
-__ZN3JSC4Heap20markProtectedObjectsEv
-__ZN3JSC12SmallStrings4markEv
-__ZN3JSC4Heap5sweepILNS_8HeapTypeE0EEEmv
-__ZN3JSC12RegExpObjectD1Ev
-__ZN3JSC12JSActivationD1Ev
-__ZN3JSC12JSActivationD2Ev
-__ZN3JSC9ArgumentsD1Ev
-__ZN3JSC9ArgumentsD2Ev
-__ZN3JSC18RegExpMatchesArrayD1Ev
-__ZN3JSC8JSObjectD1Ev
-__ZN3JSC22JSPropertyNameIteratorD1Ev
-__ZN3JSC12StringObjectD1Ev
-__ZN3JSC8JSObjectD2Ev
-__ZN3JSC4Heap5sweepILNS_8HeapTypeE1EEEmv
+__ZL11makeDivNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
+__ZNK3JSC8NullNode6isNullEv
+__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC13constructDateEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC12DateInstanceC1EPNS_9ExecStateEd
+__ZN3WTF8timeClipEd
+__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL19dateProtoFuncGetDayEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC12DateInstance9classInfoEv
+__ZNK3JSC12DateInstance26calculateGregorianDateTimeEPNS_9ExecStateE
+__ZN3JSC17DateInstanceCache3addEd
+__ZN3JSC21msToGregorianDateTimeEPNS_9ExecStateEdbRNS_17GregorianDateTimeE
+__ZN3JSC12getUTCOffsetEPNS_9ExecStateE
+__ZN3JSCL12getDSTOffsetEPNS_9ExecStateEdd
+__ZN3WTFL18calculateDSTOffsetEdd
+__ZN3WTF23dayInMonthFromDayInYearEib
+__ZN3JSCL21dateProtoFuncGetHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23dateProtoFuncGetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC14NumericStrings3addEd
+__ZN3WTFL4multERNS_6BigIntERKS0_
+__ZN3WTF6VectorIjLm16EEaSERKS1_
+__ZN3WTF6BigInt6appendEj
+__ZN3JSC8JSString4Rope20destructNonRecursiveEv
 __ZNK3JSC19JSStaticScopeObject14isDynamicScopeEv
 __ZN3JSC17ReadModifyDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC19JSStaticScopeObject14isDynamicScopeEv
 __ZN3JSC17ReadModifyDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17ReadModifyDotNodeD0Ev
-__ZN3JSC7UString10BaseString20slowIsBufferReadOnlyEv
 __ZN3JSC18BooleanConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL22callBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC18BooleanConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL22callBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZL17bracketIsAnchoredPKh
 __ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF6VectorItLm256EE14expandCapacityEm
+__ZN3WTF6VectorItLm256EE14expandCapacityEmPKt
 __ZN3JSC19FunctionConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL32constructWithFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSC19FunctionConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL32constructWithFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListE
 __ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
 __ZN3JSC12JSActivation18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC10SwitchNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC13CaseBlockNode20emitBytecodeForBlockERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_
 __ZN3JSC13CaseBlockNode18tryOptimizedSwitchERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERiS7_
 __ZN3JSCL17processClauseListEPNS_14ClauseListNodeERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERNS_10SwitchKindERbRiSB_
 __ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
 __ZN3JSC12JSActivation18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC10SwitchNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC13CaseBlockNode20emitBytecodeForBlockERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_
 __ZN3JSC13CaseBlockNode18tryOptimizedSwitchERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERiS7_
 __ZN3JSCL17processClauseListEPNS_14ClauseListNodeERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERNS_10SwitchKindERbRiSB_
-__ZN3WTF6VectorINS_6RefPtrIN3JSC5LabelEEELm8EE15reserveCapacityEm
 __ZN3JSC17BytecodeGenerator11beginSwitchEPNS_10RegisterIDENS_10SwitchInfo10SwitchTypeE
 __ZN3WTF6VectorIN3JSC10SwitchInfoELm0EE14expandCapacityEm
 __ZN3JSC17BytecodeGenerator11beginSwitchEPNS_10RegisterIDENS_10SwitchInfo10SwitchTypeE
 __ZN3WTF6VectorIN3JSC10SwitchInfoELm0EE14expandCapacityEm
-__ZN3WTF6VectorIiLm8EE14expandCapacityEm
+__ZN3WTF6VectorISt4pairIiiELm8EE14expandCapacityEmPKS2_
 __ZN3JSC17BytecodeGenerator9endSwitchEjPN3WTF6RefPtrINS_5LabelEEEPPNS_14ExpressionNodeEPS3_ii
 __ZN3JSC17BytecodeGenerator9endSwitchEjPN3WTF6RefPtrINS_5LabelEEEPPNS_14ExpressionNodeEPS3_ii
-__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14expandCapacityEm
-__ZN3JSC14CaseClauseNodeD0Ev
-__ZN3JSC14ClauseListNodeD0Ev
-__ZN3JSC13CaseBlockNodeD0Ev
-__ZN3JSC10SwitchNodeD0Ev
-__ZN3JSC5equalEPKNS_7UString3RepES3_
+__ZN3JSC9CodeBlock24addStringSwitchJumpTableEv
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14expandCapacityEmPKS2_
+__ZN3WTF11VectorMoverILb0EN3JSC15StringJumpTableEE4moveEPKS2_S5_PS2_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_NS2_14OffsetLocationEENS_18PairFirstExtractorIS7_EENS_7StrHashIS4_EENS_14PairHashTraitsINS_10HashTraitsIS4_EENSD_IS6_EEEESE_E6rehashEi
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_NS2_14OffsetLocationEENS_18PairFirstExtractorIS7_EENS_7StrHashIS4_EENS_14PairHashTraitsINS_10HashTraitsIS4_EENSD_IS6_EEEESE_E4findIS4_NS_22IdentityHashTranslatorIS4_S7_SB_EEEENS_17HashTableIteratorIS4_S7_S9_SB_SG_SE_EERKT_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_NS2_14OffsetLocationEENS_18PairFirstExtractorIS7_EENS_7StrHashIS4_EENS_14PairHashTraitsINS_10HashTraitsIS4_EENSD_IS6_EEEESE_E3addIS4_S7_NS_22IdentityHashTranslatorIS4_S7_SB_EEEES5_INS_17HashTableIteratorIS4_S7_S9_SB_SG_SE_EEbERKT_RKT0_
+__ZN3WTF9HashTableINS_6RefPtrIN3JSC11UStringImplEEESt4pairIS4_NS2_14OffsetLocationEENS_18PairFirstExtractorIS7_EENS_7StrHashIS4_EENS_14PairHashTraitsINS_10HashTraitsIS4_EENSD_IS6_EEEESE_E3addIPS3_S6_NS_29RefPtrHashMapRawKeyTranslatorISJ_S7_SG_SB_EEEES5_INS_17HashTableIteratorIS4_S7_S9_SB_SG_SE_EEbERKT_RKT0_
+__ZN3JSC15StringJumpTable14offsetForValueEPNS_11UStringImplEi
 __ZN3JSC28globalFuncEncodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL6encodeEPNS_9ExecStateERKNS_7ArgListEPKc
 __ZNK3JSC7UString10UTF8StringEb
 __ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
 __ZN3JSC28globalFuncEncodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL6encodeEPNS_9ExecStateERKNS_7ArgListEPKc
 __ZNK3JSC7UString10UTF8StringEb
 __ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
-__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC7UStringC2EPtib
-__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm16EE14expandCapacityEm
-__ZN3JSC7UString13appendNumericEi
-__ZN3JSC11concatenateEPNS_7UString3RepEi
-__ZNK3JSC8NullNode6isNullEv
-__ZN3JSC13GreaterEqNodeD0Ev
-__ZL12makeMultNodePvPN3JSC14ExpressionNodeES2_b
-__ZN3JSC8MultNodeD0Ev
-__ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF16weakRandomNumberEv
-__ZN3JSC12jsNumberCellEPNS_9ExecStateEd
+__ZN3JSC7CStringD1Ev
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm16EE14expandCapacityEmPKS3_
+__ZN3JSC8jsLessEqEPNS_9ExecStateENS_7JSValueES2_
+__ZN3WTF6VectorIN3JSC8JSString4Rope5FiberELm32EE14expandCapacityEm
+__ZL12makeMultNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
 __ZN3JSCL17mathProtoFuncCeilEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL17mathProtoFuncCeilEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC7UString3Rep11computeHashEPKti
-__ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
+__ZNK3JSC7JSValue17toPrimitiveStringEPNS_9ExecStateE
+__ZN3JSC14jsIsObjectTypeENS_7JSValueE
+__ZN3JSCL20arrayProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL20stringProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callStringConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17BytecodeGenerator29uncheckedRegisterForArgumentsEv
+__ZN3JSC23FunctionCallBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC20EvalFunctionCallNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC20EvalFunctionCallNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC20EvalFunctionCallNodeD0Ev
-__ZN3JSC11Interpreter22resolveBaseAndPropertyEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
+__ZN3JSC17BytecodeGenerator12emitCallEvalEPNS_10RegisterIDES2_S2_PNS_13ArgumentsNodeEjjj
+__ZN3JSCL26stringProtoFuncToUpperCaseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC7UString12replaceRangeEiiRKS0_
+__ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12RegExpObject4execEPNS_9ExecStateERKNS_7ArgListE
+__ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
+__ZN3WTFL37parseDateFromNullTerminatedCharactersEPKcRbRi
+__ZN3JSC14InstanceOfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitInstanceOfEPNS_10RegisterIDES2_S2_S2_
+__ZN3JSCL27isInvalidParamForInstanceOfEPNS_9ExecStateEPNS_9CodeBlockEPKNS_11InstructionENS_7JSValueERS7_
+__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
+__ZN3JSC19JSStaticScopeObject12markChildrenERNS_9MarkStackE
+__ZN3JSC22JSPropertyNameIteratorD1Ev
+__ZN3WTF21CrossThreadRefCountedINS_16OwnFastMallocPtrItEEE5derefEv
+__ZN3JSC9parseDateEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC37parseDateFromNullTerminatedCharactersEPNS_9ExecStateEPKc
+__ZN3JSCL21dateProtoFuncSetHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23setNewValueFromTimeArgsEPNS_9ExecStateENS_7JSValueERKNS_7ArgListEib
+__ZN3JSC21gregorianDateTimeToMSEPNS_9ExecStateERKNS_17GregorianDateTimeEdb
+__ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC13jsAddSlowCaseEPNS_9ExecStateENS_7JSValueES2_
+__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC18globalFuncParseIntEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC15toInt32SlowCaseEdRb
+__ZN3JSC12DateInstanceD1Ev
+__ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
+__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC15globalFuncIsNaNEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC15globalFuncIsNaNEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC11Interpreter8callEvalEPNS_9ExecStateEPNS_12RegisterFileEPNS_8RegisterEiiRNS_7JSValueE
-__ZN3JSC13LiteralParser5Lexer3lexERNS1_18LiteralParserTokenE
-__ZN3JSC13LiteralParser5parseENS0_11ParserStateE
-__ZNK3WTF7HashMapINS_6RefPtrIN3JSC7UString3RepEEENS1_INS2_8EvalNodeEEENS_7StrHashIS5_EENS_10HashTraitsIS5_EENSA_IS7_EEE3getEPS4_
-__ZN3JSC6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE
-__ZN3WTF9HashTableINS_6RefPtrIN3JSC7UString3RepEEESt4pairIS5_NS1_INS2_8EvalNodeEEEENS_18PairFirstExtractorIS9_EENS_7StrHashIS5_EENS_14PairHashTraitsINS_10HashTraitsIS5_EENSF_IS8_EEEESG_E6expandEv
-__ZN3JSC9ExecState9thisValueEv
-__ZN3JSC11Interpreter7executeEPNS_8EvalNodeEPNS_9ExecStateEPNS_8JSObjectEiPNS_14ScopeChainNodeEPNS_7JSValueE
-__ZN3JSC8EvalNode16generateBytecodeEPNS_14ScopeChainNodeE
-__ZN3JSC17BytecodeGeneratorC2EPNS_8EvalNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_7UString3RepEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISE_EENS_26SymbolTableIndexHashTraitsEEEPNS_13EvalCodeBlockE
-__ZN3JSC8EvalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC11Interpreter11resolveBaseEPNS_9ExecStateEPNS_11InstructionE
-__ZN3JSC10LessEqNodeD0Ev
-__ZN3JSC16globalFuncEscapeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZThn12_N3JSC8EvalNodeD0Ev
-__ZN3JSC8EvalNodeD0Ev
-__ZN3JSC22JSPropertyNameIterator4markEv
-__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC21ReadModifyResolveNodeD0Ev
+__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL29objectProtoFuncHasOwnPropertyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZNK3JSC8JSObject14hasOwnPropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC9CodeBlock27addImmediateSwitchJumpTableEv
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE15reserveCapacityEm
+__ZN3WTF6VectorIiLm0EE4fillERKim
+__ZN3JSC15SimpleJumpTable14offsetForValueEii
+__ZN3JSC11Interpreter22resolveBaseAndPropertyEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
+__ZN3JSCL24regExpConstructorDollar2EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar3EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZN3JSCL24regExpConstructorDollar4EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
+__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
+__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEPNS_9ExecStateEj
+__ZN3JSC9CodeBlock34reparseForExceptionInfoIfNecessaryEPNS_9ExecStateE
+__ZN3JSC18FunctionExecutable20reparseExceptionInfoEPNS_12JSGlobalDataEPNS_14ScopeChainNodeEPNS_9CodeBlockE
+__ZN3WTF6OwnPtrIN3JSC13ExceptionInfoEE3setEPS2_
 __ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL6decodeEPNS_9ExecStateERKNS_7ArgListEPKcb
 __ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL6decodeEPNS_9ExecStateERKNS_7ArgListEPKcb
-__ZNK3JSC12JSNumberCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
-__ZN3JSC7UString13appendNumericEd
-__ZN3JSC11concatenateEPNS_7UString3RepEd
-__ZN3JSC14jsIsObjectTypeENS_7JSValueE
-__ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
-__ZL11makeDivNodePvPN3JSC14ExpressionNodeES2_b
-__ZN3JSC7DivNodeD0Ev
-__ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSC13constructDateEPNS_9ExecStateERKNS_7ArgListE
-__ZN3WTF17getCurrentUTCTimeEv
-__ZN3WTF8timeClipEd
-__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC12DateInstance9classInfoEv
-__ZNK3JSC12DateInstance21msToGregorianDateTimeEdbRN3WTF17GregorianDateTimeE
-__ZN3WTF21msToGregorianDateTimeEdbRNS_17GregorianDateTimeE
-__ZN3WTF12getUTCOffsetEv
-__ZN3WTFL12getDSTOffsetEdd
-__ZN3JSCL21dateProtoFuncGetHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF13tryFastMallocEm
-__ZN3JSC10BitAndNodeD0Ev
-__ZN3JSC18globalFuncParseIntEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17PrefixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21ReadModifyBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZL17makeLeftShiftNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
+__ZL18makeRightShiftNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
+__ZN3JSC17BytecodeGenerator10emitPreDecEPNS_10RegisterIDE
+__ZN3JSCL25stringProtoFuncCharCodeAtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11DoWhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL8parseIntERKNS_7UStringEi
 __ZN3JSCL8parseIntERKNS_7UStringEi
-__ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC10JSONObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL22JSONProtoFuncStringifyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11StringifierC2EPNS_9ExecStateENS_7JSValueES3_
+__ZN3JSCL20unwrapBoxedPrimitiveEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC11Stringifier9stringifyENS_7JSValueE
+__ZN3JSC11Stringifier22appendStringifiedValueERNS_13StringBuilderENS_7JSValueEPNS_8JSObjectERKNS_27PropertyNameForFunctionCallE
+__ZN3JSC11Stringifier6toJSONENS_7JSValueERKNS_27PropertyNameForFunctionCallE
+__ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE
+__ZN3JSC11Stringifier6Holder18appendNextPropertyERS0_RNS_13StringBuilderE
+__ZN3JSC11Stringifier6indentEv
+__ZNK3JSC7UString6substrEii
+__ZNK3JSC11Stringifier12startNewLineERNS_13StringBuilderE
+__ZN3JSC11Stringifier18appendQuotedStringERNS_13StringBuilderERKNS_7UStringE
+__ZN3JSC11Stringifier8unindentEv
+__ZN3JSC11StringifierD2Ev
 __ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
 __ZN3JSC26createNotAnObjectErrorStubEPNS_9ExecStateEb
 __ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
 __ZN3JSC26createNotAnObjectErrorStubEPNS_9ExecStateEb
 __ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
@@ -774,112 +954,42 @@ __ZN3JSC11Interpreter14throwExceptionERPNS_9ExecStateERNS_7JSValueEjb
 __ZNK3JSC22JSNotAnObjectErrorStub22isNotAnObjectErrorStubEv
 __ZN3JSC22createNotAnObjectErrorEPNS_9ExecStateEPNS_22JSNotAnObjectErrorStubEjPNS_9CodeBlockE
 __ZN3JSC9CodeBlock37getByIdExceptionInfoForBytecodeOffsetEPNS_9ExecStateEjRNS_8OpcodeIDE
 __ZNK3JSC22JSNotAnObjectErrorStub22isNotAnObjectErrorStubEv
 __ZN3JSC22createNotAnObjectErrorEPNS_9ExecStateEPNS_22JSNotAnObjectErrorStubEjPNS_9CodeBlockE
 __ZN3JSC9CodeBlock37getByIdExceptionInfoForBytecodeOffsetEPNS_9ExecStateEjRNS_8OpcodeIDE
-__ZN3JSC9CodeBlock34reparseForExceptionInfoIfNecessaryEPNS_9ExecStateE
 __ZNK3JSC10ScopeChain10localDepthEv
 __ZNK3JSC12JSActivation9classInfoEv
 __ZNK3JSC10ScopeChain10localDepthEv
 __ZNK3JSC12JSActivation9classInfoEv
-__ZN3JSC6Parser7reparseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPS5_
-__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm0EEEPNS6_IPNS_12FuncDeclNodeELm0EEERKNS_10SourceCodeEji
-__ZN3JSC13StatementNode6setLocEii
-__ZN3JSC16FunctionBodyNode14copyParametersEv
-__ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm
-__ZN3JSC16FunctionBodyNode31bytecodeForExceptionInfoReparseEPNS_14ScopeChainNodeEPNS_9CodeBlockE
 __ZN3JSC9CodeBlock43hasGlobalResolveInstructionAtBytecodeOffsetEj
 __ZN3JSC9CodeBlock32expressionRangeForBytecodeOffsetEPNS_9ExecStateEjRiS3_S3_
 __ZN3JSCL18createErrorMessageEPNS_9ExecStateEPNS_9CodeBlockEiiiNS_7JSValueENS_7UStringE
 __ZN3JSC9CodeBlock43hasGlobalResolveInstructionAtBytecodeOffsetEj
 __ZN3JSC9CodeBlock32expressionRangeForBytecodeOffsetEPNS_9ExecStateEjRiS3_S3_
 __ZN3JSCL18createErrorMessageEPNS_9ExecStateEPNS_9CodeBlockEiiiNS_7JSValueENS_7UStringE
+__ZN3JSC10makeStringIPKcNS_7UStringES2_S3_S2_S3_S2_EES3_T_T0_T1_T2_T3_T4_T5_
 __ZN3JSC5Error6createEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringEilS6_
 __ZN3JSC22NativeErrorConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSC5Error6createEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringEilS6_
 __ZN3JSC22NativeErrorConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
 __ZN3JSCL35constructWithNativeErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSC22NativeErrorConstructor9constructEPNS_9ExecStateERKNS_7ArgListE
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
 __ZN3JSCL35constructWithNativeErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSC22NativeErrorConstructor9constructEPNS_9ExecStateERKNS_7ArgListE
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC20MarkedArgumentBufferD1Ev
 __ZN3JSC9CodeBlock24handlerForBytecodeOffsetEj
 __ZN3JSC11Interpreter20createExceptionScopeEPNS_9ExecStateEPKNS_11InstructionE
 __ZN3JSC9CodeBlock24handlerForBytecodeOffsetEj
 __ZN3JSC11Interpreter20createExceptionScopeEPNS_9ExecStateEPKNS_11InstructionE
-__ZN3JSC23FunctionCallBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC23FunctionCallBracketNodeD0Ev
 __ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL19dateProtoFuncGetDayEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF6VectorIjLm16EE6resizeEm
+__ZN3JSC16globalFuncEscapeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL24dateProtoFuncToGMTStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL24dateProtoFuncToGMTStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC10formatTimeERKN3WTF17GregorianDateTimeEb
-__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZNK3JSC12JSNumberCell8toObjectEPNS_9ExecStateE
-__ZN3JSC15constructNumberEPNS_9ExecStateENS_7JSValueE
+__ZNK3JSC12DateInstance29calculateGregorianDateTimeUTCEPNS_9ExecStateE
+__ZN3JSC20formatDateUTCVariantERKNS_17GregorianDateTimeERA100_c
+__ZN3JSC13formatTimeUTCERKNS_17GregorianDateTimeERA100_c
+__ZN3JSC10makeStringIPcPKcS1_EENS_7UStringET_T0_T1_
+__ZN3JSC18jsNontrivialStringEPNS_12JSGlobalDataERKNS_7UStringE
 __ZN3JSCL23numberProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL23numberProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC12JSNumberCell8toStringEPNS_9ExecStateE
 __ZN3JSC14PostfixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC14PostfixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC14PostfixDotNodeD0Ev
-__ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL20stringProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL22objectProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL22objectProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC14InstanceOfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator14emitInstanceOfEPNS_10RegisterIDES2_S2_S2_
-__ZN3JSC14InstanceOfNodeD0Ev
-__ZN3JSCL27isInvalidParamForInstanceOfEPNS_9ExecStateEPNS_9CodeBlockEPKNS_11InstructionENS_7JSValueERS7_
-__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
-__ZN3JSCL20arrayProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL21callStringConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC12StringObject8toStringEPNS_9ExecStateE
-__ZN3JSCL26stringProtoFuncToUpperCaseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7UString12replaceRangeEiiRKS0_
-__ZN3JSCL23stringProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC13jsAddSlowCaseEPNS_9ExecStateENS_7JSValueES2_
-__ZNK3JSC12StringObject9classInfoEv
-__ZN3WTFL15dateToDayInYearEiii
-__ZN3JSCL23dateProtoFuncGetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL7dateNowEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC19JSStaticScopeObjectD1Ev
-__ZN3JSC19JSStaticScopeObjectD2Ev
-__ZN3JSC13ErrorInstanceD1Ev
-__ZN3JSC13JSNotAnObjectD1Ev
-__ZN3JSC22JSNotAnObjectErrorStubD1Ev
-__ZN3JSC12NumberObjectD1Ev
-__ZN3JSC12DateInstanceD1Ev
-__ZN3JSC17PrefixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17PrefixResolveNodeD0Ev
-__ZN3JSCL29objectProtoFuncHasOwnPropertyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC17ObjectConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL30constructWithObjectConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSC17ObjectConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL30constructWithObjectConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSCL24regExpConstructorDollar2EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3JSCL24regExpConstructorDollar3EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3JSCL24regExpConstructorDollar4EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
-__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEPNS_9ExecStateEj
-__ZN3JSC21ReadModifyBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC7ModNodeD0Ev
-__ZN3JSC21ReadModifyBracketNodeD0Ev
-__ZN3JSC10BitXOrNodeD0Ev
-__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZL17makeLeftShiftNodePvPN3JSC14ExpressionNodeES2_b
-__ZL18makeRightShiftNodePvPN3JSC14ExpressionNodeES2_b
-__ZN3JSC13LeftShiftNodeD0Ev
-__ZN3JSC14RightShiftNodeD0Ev
-__ZN3JSCL25stringProtoFuncCharCodeAtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC15toInt32SlowCaseEdRb
-__ZN3JSC10NegateNodeD0Ev
-__ZN3JSC11DoWhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC11DoWhileNodeD0Ev
-__ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17PrefixBracketNodeD0Ev
-__ZN3JSC10JSONObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL22JSONProtoFuncStringifyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC11StringifierC2EPNS_9ExecStateENS_7JSValueES3_
-__ZN3JSC11Stringifier9stringifyENS_7JSValueE
-__ZN3JSC11Stringifier22appendStringifiedValueERNS_7UStringENS_7JSValueEPNS_8JSObjectERKNS_27PropertyNameForFunctionCallE
-__ZNK3JSC6JSCell9getStringERNS_7UStringE
-__ZN3JSC11Stringifier6Holder18appendNextPropertyERS0_RNS_7UStringE
-__ZNK3JSC7UString6substrEii
-__ZNK3JSC7UStringixEi
-__ZN3JSC11Stringifier18appendQuotedStringERNS_7UStringERKS1_
-__ZN3JSC7UString6appendEPKti
-__ZN3JSC11StringifierD2Ev
+__ZN3WTF9HashTableIdSt4pairIdN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E4findIdNS_22IdentityHashTranslatorIdS4_S8_EEEENS_17HashTableIteratorIdS4_S6_S8_SD_SB_EERKT_
+__ZN3WTF9HashTableIdSt4pairIdN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E6rehashEi
+__ZN3WTF9HashTableIdSt4pairIdN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E3addIdS3_NS_17HashMapTranslatorIS4_SD_S8_EEEES1_INS_17HashTableIteratorIdS4_S6_S8_SD_SB_EEbERKT_RKT0_
 __ZN3JSCL18JSONProtoFuncParseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL18JSONProtoFuncParseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC13LiteralParser5Lexer3lexERNS1_18LiteralParserTokenE
+__ZN3JSC13LiteralParser5parseENS0_11ParserStateE
 __ZN3JSC13LiteralParser5Lexer9lexStringILNS0_10ParserModeE0EEENS0_9TokenTypeERNS1_18LiteralParserTokenE
 __ZN3JSC13LiteralParser5Lexer9lexNumberERNS1_18LiteralParserTokenE
 __ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateEjNS_7JSValueE
 __ZN3JSC13LiteralParser5Lexer9lexStringILNS0_10ParserModeE0EEENS0_9TokenTypeERNS1_18LiteralParserTokenE
 __ZN3JSC13LiteralParser5Lexer9lexNumberERNS1_18LiteralParserTokenE
 __ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateEjNS_7JSValueE
@@ -888,75 +998,67 @@ __ZNK3JSC8JSObject19isWatchdogExceptionEv
 __ZN3JSC11Interpreter15unwindCallFrameERPNS_9ExecStateENS_7JSValueERjRPNS_9CodeBlockE
 __ZN3JSC19JSStaticScopeObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
 __ZN3JSC11Interpreter15unwindCallFrameERPNS_9ExecStateENS_7JSValueERjRPNS_9CodeBlockE
 __ZN3JSC19JSStaticScopeObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
-__ZN3JSC17PropertyNameArray3addEPNS_7UString3RepE
-__ZN3WTF7HashSetIPN3JSC7UString3RepENS_7PtrHashIS4_EENS_10HashTraitsIS4_EEE3addERKS4_
-__ZN3WTF9HashTableIPN3JSC7UString3RepES4_NS_17IdentityExtractorIS4_EENS_7PtrHashIS4_EENS_10HashTraitsIS4_EESA_E6rehashEi
-__ZN3JSC17PrototypeFunctionD1Ev
-__ZN3JSC15ObjectPrototypeD1Ev
-__ZN3JSC17FunctionPrototypeD1Ev
+__ZN3JSC17PropertyNameArray3addEPNS_11UStringImplE
+__ZN3WTF9HashTableIPN3JSC11UStringImplES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E3addIS3_S3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEESt4pairINS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EEbERKT_RKT0_
+__ZN3WTF9HashTableIPN3JSC11UStringImplES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC4Heap17collectAllGarbageEv
+__ZN3JSC4Heap5sweepEv
 __ZN3JSC14JSGlobalObjectD2Ev
 __ZN3JSC14JSGlobalObjectD2Ev
-__ZN3JSC18GlobalEvalFunctionD1Ev
-__ZN3JSC10JSONObjectD1Ev
-__ZN3JSC10MathObjectD1Ev
-__ZN3JSC22NativeErrorConstructorD1Ev
-__ZN3JSC16ErrorConstructorD1Ev
-__ZN3JSC17RegExpConstructorD1Ev
-__ZN3JSC15DateConstructorD1Ev
-__ZN3JSC17NumberConstructorD1Ev
-__ZN3JSC18BooleanConstructorD1Ev
-__ZN3JSC17StringConstructorD1Ev
-__ZN3JSC16ArrayConstructorD1Ev
-__ZN3JSC19FunctionConstructorD1Ev
-__ZN3JSC17ObjectConstructorD1Ev
-__ZN3JSC20NativeErrorPrototypeD1Ev
-__ZN3JSC14ErrorPrototypeD1Ev
-__ZN3JSC15RegExpPrototypeD1Ev
-__ZN3JSC13DatePrototypeD1Ev
-__ZN3JSC12DateInstanceD2Ev
-__ZN3JSC15NumberPrototypeD1Ev
-__ZN3JSC16BooleanPrototypeD1Ev
-__ZN3JSC15StringPrototypeD1Ev
+__ZN3JSC17FunctionPrototypeD1Ev
+__ZN3JSC15ObjectPrototypeD1Ev
 __ZN3JSC14ArrayPrototypeD1Ev
 __ZN3JSC14ArrayPrototypeD1Ev
+__ZN3JSC15StringPrototypeD1Ev
+__ZN3JSC16BooleanPrototypeD1Ev
+__ZN3JSC15NumberPrototypeD1Ev
+__ZN3JSC13DatePrototypeD1Ev
+__ZN3JSC15RegExpPrototypeD1Ev
+__ZN3JSC14ErrorPrototypeD1Ev
+__ZN3JSC13ErrorInstanceD2Ev
+__ZN3JSC20NativeErrorPrototypeD1Ev
+__ZN3JSC17ObjectConstructorD1Ev
+__ZN3JSC19FunctionConstructorD1Ev
+__ZN3JSC16ArrayConstructorD1Ev
+__ZN3JSC17StringConstructorD1Ev
+__ZN3JSC18BooleanConstructorD1Ev
+__ZN3JSC17NumberConstructorD1Ev
+__ZN3JSC15DateConstructorD1Ev
+__ZN3JSC17RegExpConstructorD1Ev
+__ZN3JSC16ErrorConstructorD1Ev
+__ZN3JSC22NativeErrorConstructorD1Ev
+__ZN3JSC10MathObjectD1Ev
+__ZN3JSC10JSONObjectD1Ev
+__ZN3JSC18GlobalEvalFunctionD1Ev
+__ZN3JSC22JSNotAnObjectErrorStubD1Ev
+__ZN3JSC13JSNotAnObjectD1Ev
+__ZN3JSC13ErrorInstanceD1Ev
+__ZN3JSC19JSStaticScopeObjectD1Ev
+__ZN3JSC19JSStaticScopeObjectD2Ev
 __ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator15emitDeleteByValEPNS_10RegisterIDES2_S2_
 __ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator15emitDeleteByValEPNS_10RegisterIDES2_S2_
-__ZN3JSC17DeleteBracketNodeD0Ev
 __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZNK3JSC8JSObject9classNameEv
 __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZNK3JSC8JSObject9classNameEv
+__ZN3JSC10makeStringIPKcNS_7UStringES2_EES3_T_T0_T1_
 __ZN3JSC17StringConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL30constructWithStringConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
 __ZN3JSC17StringConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL30constructWithStringConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
+__ZN3JSC12StringObjectC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7UStringE
 __ZN3JSC12RegExpObject11getCallDataERNS_8CallDataE
 __ZN3JSC12RegExpObject11getCallDataERNS_8CallDataE
-__ZN3JSC4Heap15recordExtraCostEm
-__ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
+__ZN3JSCL28substituteBackreferencesSlowERKNS_7UStringES2_PKiPNS_6RegExpEi
 __ZN3JSCL21dateProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL21dateProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC10formatDateERKNS_17GregorianDateTimeERA100_c
+__ZN3JSC10formatTimeERKNS_17GregorianDateTimeERA100_c
 __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
 __ZN3JSCL20dateProtoFuncGetDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
 __ZN3JSCL20dateProtoFuncGetDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL18stringFromCharCodeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC11Interpreter11resolveSkipEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
-__ZN3JSC9Structure27despecifyDictionaryFunctionERKNS_10IdentifierE
-__ZN3JSC17DeleteResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17DeleteResolveNodeD0Ev
-__ZN3JSCL21arrayProtoFuncUnShiftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC11Interpreter14uncachePutByIDEPNS_9CodeBlockEPNS_11InstructionE
-__ZNK3JSC9Arguments9classInfoEv
-__ZN3JSC9Arguments15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
-__ZN3JSC9Arguments3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
-__ZN3WTF6VectorIPN3JSC9StructureELm8EE14expandCapacityEm
-__ZN3JSC12StringObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
-__ZN3JSC9ExecState11stringTableEPS0_
+__ZN3JSC9MarkStack12releaseStackEPvm
+__ZN3JSC14StructureChainD1Ev
+__ZN3WTF11OwnArrayPtrINS_6RefPtrIN3JSC9StructureEEEE10safeDeleteEv
+__ZN3JSC4Heap9freeBlockEm
+__ZN3JSC4Heap12freeBlockPtrEPNS_14CollectorBlockE
+__ZN3WTF13tryFastCallocEmm
+__ZN3WTF10fastCallocILb0EEEPvmm
 __ZN3JSCL16mathProtoFuncMinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL16mathProtoFuncMinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTFL7multaddERNS_6BigIntEii
-__ZN3WTF6VectorIjLm16EEaSERKS1_
-__ZN3WTFL4multERNS_6BigIntERKS0_
-__ZN3JSC18PostfixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC18PostfixBracketNodeD0Ev
-__ZN3JSCL21arrayProtoFuncReverseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__Z15jsc_pcre_xclassiPKh
-__ZN3JSC8VoidNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC8VoidNodeD0Ev
-__ZN3JSC12JSActivation3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZNK3JSC9ArrayNode13isSimpleArrayEv
-__ZN3JSCL21stringProtoFuncCharAtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17NumberConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callNumberConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL18regExpObjectSourceEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
 __ZN3JSC17RegExpConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL21callRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL18regExpObjectSourceEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
 __ZN3JSC17RegExpConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL21callRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
@@ -965,111 +1067,91 @@ __ZN3JSCL18arrayProtoFuncSortEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7Arg
 __ZN3JSC7JSArray4sortEPNS_9ExecStateE
 __ZN3JSC7JSArray17compactForSortingEv
 __ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC7JSArray4sortEPNS_9ExecStateE
 __ZN3JSC7JSArray17compactForSortingEv
 __ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3WTF6VectorIN3JSC7UString5RangeELm16EE14expandCapacityEm
-__ZN3WTF6VectorIN3JSC7UStringELm16EE14expandCapacityEm
-__ZN3JSCL17arrayProtoFuncPopEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC7JSArray3popEv
+__ZN3JSC9Structure27despecifyDictionaryFunctionERKNS_10IdentifierE
+__ZN3JSCL18stringFromCharCodeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC23jsSingleCharacterStringEPNS_12JSGlobalDataEt
+__ZN3WTF6VectorIN3JSC7UString5RangeELm16EE15reserveCapacityEm
+__ZN3WTF6VectorIN3JSC7UStringELm16EE15reserveCapacityEm
+__ZN3JSC11Interpreter8callEvalEPNS_9ExecStateEPNS_12RegisterFileEPNS_8RegisterEiiRNS_7JSValueE
+__ZN3JSC13EvalCodeCache3getEPNS_9ExecStateERKNS_7UStringEPNS_14ScopeChainNodeERNS_7JSValueE
+__ZN3JSC14EvalExecutable7compileEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPNS_8DebuggerEPNS_9ExecStateERKNS_10SourceCodeEPiPNS_7UStringE
+__ZN3JSC8EvalNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_IPNS_16FunctionBodyNodeELm0EEERKNS_10SourceCodeEji
+__ZN3JSC13EvalCodeBlockC2EPNS_14EvalExecutableEPNS_14JSGlobalObjectEN3WTF10PassRefPtrINS_14SourceProviderEEEi
+__ZN3JSC17BytecodeGeneratorC1EPNS_8EvalNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_11UStringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISD_EENS_26SymbolTableIndexHashTraitsEEEPNS_13EvalCodeBlockE
+__ZN3JSC17BytecodeGeneratorC2EPNS_8EvalNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrINS_11UStringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS9_10HashTraitsISD_EENS_26SymbolTableIndexHashTraitsEEEPNS_13EvalCodeBlockE
+__ZN3JSC8EvalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZThn12_N3JSC8EvalNodeD0Ev
+__ZN3JSC9ExecState9thisValueEv
+__ZN3JSC11Interpreter7executeEPNS_14EvalExecutableEPNS_9ExecStateEPNS_8JSObjectEiPNS_14ScopeChainNodeEPNS_7JSValueE
+__ZN3JSC14EvalExecutableD0Ev
+__ZN3JSC13EvalCodeBlockD0Ev
+__ZN3JSCL21stringProtoFuncCharAtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC26jsSingleCharacterSubstringEPNS_12JSGlobalDataERKNS_7UStringEj
+__ZN3JSC8JSString18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
 __ZN3JSCL21functionProtoFuncCallEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL21functionProtoFuncCallEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC17DeleteResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11Interpreter11resolveBaseEPNS_9ExecStateEPNS_11InstructionE
 __ZN3JSC12JSActivation14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC12JSActivation14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSCL9dateParseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12RegExpObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSCL24setRegExpObjectLastIndexEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
-__ZN3JSCL28regExpConstructorLeftContextEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC28createUndefinedVariableErrorEPNS_9ExecStateERKNS_10IdentifierEjPNS_9CodeBlockE
-__ZN3JSC36constructBooleanFromImmediateBooleanEPNS_9ExecStateENS_7JSValueE
-__ZN3JSCL26stringProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7JSValue20toIntegerPreserveNaNEPNS_9ExecStateE
-__ZNK3JSC7UString5rfindERKS0_i
-__ZN3JSC19globalFuncEncodeURIEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC13UnaryPlusNode14stripUnaryPlusEv
-__ZN3JSC8JSString18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
-__ZN3JSC13BooleanObjectD1Ev
-__ZN3WTF17TCMalloc_PageHeap3NewEm
-__ZNK3JSC21UStringSourceProvider8getRangeEii
-__ZN3JSCL23dateProtoFuncGetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
-__ZN3JSCL24dateProtoFuncGetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL20dateProtoFuncSetYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF21gregorianDateTimeToMSERKNS_17GregorianDateTimeEdb
-__ZN3JSCL27compareByStringPairForQSortEPKvS1_
-__ZN3JSCL29regExpConstructorRightContextEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZNK3JSC12NumberObject9classInfoEv
-__ZN3JSCL19isNonASCIIIdentPartEi
-__ZN3JSC8EvalNode4markEv
-__ZN3WTF7Unicode18UTF8SequenceLengthEc
-__ZN3WTF7Unicode18decodeUTF8SequenceEPKc
-__ZN3JSC18globalFuncIsFiniteEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL24booleanProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL24dateProtoFuncToUTCStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF10PassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
-__ZN3JSC16InternalFunction4nameEPNS_12JSGlobalDataE
-__ZN3JSC16ArrayConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL20callArrayConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL21stringProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZNK3JSC8JSString8toObjectEPNS_9ExecStateE
-__ZN3JSC17ObjectConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL21callObjectConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC13LiteralParser5Lexer9lexStringILNS0_10ParserModeE1EEENS0_9TokenTypeERNS1_18LiteralParserTokenE
-__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE14expandCapacityEmPKS4_
-__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE15reserveCapacityEm
-__ZN3JSCL16mathProtoFuncAbsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL22numberProtoFuncToFixedEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL16integerPartNoExpEd
-__ZN3JSCL16mathProtoFuncLogEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL16mathProtoFuncPowEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF13tryFastCallocEmm
-__ZN3JSC7JSArray11sortNumericEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
-__ZN3JSCL22compareNumbersForQSortEPKvS1_
-__ZN3JSCL22functionProtoFuncApplyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC9Arguments11fillArgListEPNS_9ExecStateERNS_20MarkedArgumentBufferE
-__ZN3JSC7JSArray16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
-__ZN3JSC9ExecState10arrayTableEPS0_
-__ZN3JSCL23regExpProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL18regExpObjectGlobalEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3JSCL22regExpObjectIgnoreCaseEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZN3JSCL21regExpObjectMultilineEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZNK3JSC12JSNumberCell12toThisObjectEPNS_9ExecStateE
-__ZN3JSCL22numberProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12NumberObject11getJSNumberEv
-__ZNK3JSC7JSValue16synthesizeObjectEPNS_9ExecStateE
-__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSCL22errorProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC10JSFunction15argumentsGetterEPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
-__ZNK3JSC11Interpreter17retrieveArgumentsEPNS_9ExecStateEPNS_10JSFunctionE
-__ZN3JSCL21dateProtoFuncSetMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL23setNewValueFromDateArgsEPNS_9ExecStateENS_7JSValueERKNS_7ArgListEib
-__ZN3JSCL20dateProtoFuncSetDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC9BitOrNodeD0Ev
-__ZN3JSC12JSGlobalData6createEb
+__ZN3JSC18PostfixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSCL21arrayProtoFuncUnShiftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC10JSFunction19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC12JSGlobalData6createEv
 __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
 __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
-__ZN3JSC7CStringD1Ev
+__ZN3JSC12JSGlobalData13startSamplingEv
+__ZN3JSC11Interpreter13startSamplingEv
+__ZN3JSC12JSGlobalData12stopSamplingEv
+__ZN3JSC11Interpreter12stopSamplingEv
 __ZN3JSCL17mathProtoFuncSqrtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL17mathProtoFuncSqrtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC11Interpreter14uncachePutByIDEPNS_9CodeBlockEPNS_11InstructionE
+__ZN3JSCL16mathProtoFuncAbsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL16mathProtoFuncCosEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL16mathProtoFuncSinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL16mathProtoFuncCosEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL16mathProtoFuncSinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC14BitwiseNotNodeD0Ev
-__ZN3JSC22UnsignedRightShiftNodeD0Ev
+__ZN3JSC16ArrayConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL20callArrayConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF6VectorIPN3JSC9StructureELm8EE14expandCapacityEmPKS3_
+__ZN3WTFL3i2bERNS_6BigIntEi
+__ZN3WTFL3b2dERKNS_6BigIntEPi
 __ZN3JSC16toUInt32SlowCaseEdRb
 __ZN3JSC16toUInt32SlowCaseEdRb
-__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14expandCapacityEm
-__ZN3WTF6VectorIiLm0EE15reserveCapacityEm
-__ZN3JSC15SimpleJumpTable14offsetForValueEii
+__ZN3WTF29RefPtrHashMapRawKeyTranslatorIPN3JSC11UStringImplESt4pairINS_6RefPtrIS2_EENS5_INS1_14EvalExecutableEEEENS_14PairHashTraitsINS_10HashTraitsIS6_EENSB_IS8_EEEENS_7StrHashIS6_EEE9translateERS9_S3_RKS8_
+__ZN3JSC11Interpreter11resolveSkipEPNS_9ExecStateEPNS_11InstructionERNS_7JSValueE
+__ZN3JSCL24dateProtoFuncGetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL23dateProtoFuncGetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC9CodeBlock27addCharacterSwitchJumpTableEv
+__ZN3JSCL16mathProtoFuncPowEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC7JSArray19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC9ExecState10arrayTableEPS0_
 __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
 __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
-__ZN3WTF7HashSetIPN3JSC20MarkedArgumentBufferENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E3addIS3_S3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEESt4pairINS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EEbERKT_RKT0_
 __ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
 __ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_
+__ZN3JSC15ObjectPrototype3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSCL16mathProtoFuncLogEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC13LiteralParser5Lexer9lexStringILNS0_10ParserModeE1EEENS0_9TokenTypeERNS1_18LiteralParserTokenE
+__ZNK3JSC9ArrayNode13isSimpleArrayEv
+__ZNK3JSC9ArrayNode14toArgumentListEPNS_12JSGlobalDataE
+__ZN3WTF9HashTableIPN3JSC11UStringImplES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_
 __ZN3JSC7JSArray4sortEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
 __ZN3JSC7JSArray4sortEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
+__ZN3WTF6VectorIN3JSC26AVLTreeNodeForArrayCompareELm0EE6resizeEm
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi
+__ZN3JSC32AVLTreeAbstractorForArrayCompare15compare_key_keyENS_7JSValueES1_
 __ZN3JSCltERKNS_7UStringES2_
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi
 __ZN3JSCltERKNS_7UStringES2_
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi
+__ZN3JSCL21stringProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
+__ZN3JSC11Interpreter14dumpSampleDataEPNS_9ExecStateE
 __ZN3JSC4Heap7destroyEv
 __ZN3JSC4Heap7destroyEv
+__ZN3JSC4Heap10freeBlocksEv
+__ZN3JSC14JSGlobalObject25destroyJSGlobalObjectDataEPv
+__ZN3JSC14JSGlobalObject18JSGlobalObjectDataD2Ev
 __ZN3JSC12JSGlobalDataD1Ev
 __ZN3JSC12JSGlobalDataD2Ev
 __ZN3JSC12RegisterFileD1Ev
 __ZNK3JSC9HashTable11deleteTableEv
 __ZN3JSC5LexerD1Ev
 __ZN3JSC12JSGlobalDataD1Ev
 __ZN3JSC12JSGlobalDataD2Ev
 __ZN3JSC12RegisterFileD1Ev
 __ZNK3JSC9HashTable11deleteTableEv
 __ZN3JSC5LexerD1Ev
-__ZN3JSC5LexerD2Ev
-__ZN3WTF20deleteAllPairSecondsIP24OpaqueJSClassContextDataKNS_7HashMapIP13OpaqueJSClassS2_NS_7PtrHashIS5_EENS_10HashTraitsIS5_EENS8_IS2_EEEEEEvRT0_
 __ZN3JSC17CommonIdentifiersD2Ev
 __ZN3JSC21deleteIdentifierTableEPNS_15IdentifierTableE
 __ZN3JSC17CommonIdentifiersD2Ev
 __ZN3JSC21deleteIdentifierTableEPNS_15IdentifierTableE
+__ZN3JSC15IdentifierTableD2Ev
 __ZN3JSC4HeapD1Ev
 __ZN3JSC4HeapD1Ev
-__ZN3JSC12SmallStringsD1Ev
+__ZN3JSC14NumericStringsD1Ev
+__ZN3JSC12SmallStringsD1Ev
\ No newline at end of file
index 3ae3ec6dd3bccc2af31e7cca009a3680325321b8..d6f6caabe527736b07e8d4782a8148a3b54b3e92 100644 (file)
@@ -1625,7 +1625,6 @@ __ZN3JSC18EmptyStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10Registe
 __ZN3JSCL27compareByStringPairForQSortEPKvS1_
 __Z22jsc_pcre_ucp_othercasej
 __ZN3JSCL35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSCL27compareByStringPairForQSortEPKvS1_
 __Z22jsc_pcre_ucp_othercasej
 __ZN3JSCL35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC8JSObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
 __ZN3WTF7HashMapIjN3JSC7JSValueENS_7IntHashIjEENS_10HashTraitsIjEENS5_IS2_EEE3setERKjRKS2_
 __ZN3WTF9HashTableIjSt4pairIjN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEE
 __ZN3JSC12RegisterFile21releaseExcessCapacityEv
 __ZN3WTF7HashMapIjN3JSC7JSValueENS_7IntHashIjEENS_10HashTraitsIjEENS5_IS2_EEE3setERKjRKS2_
 __ZN3WTF9HashTableIjSt4pairIjN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEE
 __ZN3JSC12RegisterFile21releaseExcessCapacityEv
@@ -1841,7 +1840,6 @@ __ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE
 __ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
 __ZN3JSCL27objectProtoFuncLookupSetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
 __ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
 __ZN3JSCL27objectProtoFuncLookupSetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3JSC16JSVariableObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj
 __ZN3JSC9ExecState22regExpConstructorTableEPS0_
 __ZN3JSCL24regExpConstructorDollar7EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
 __ZN3JSCL24regExpConstructorDollar8EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
 __ZN3JSC9ExecState22regExpConstructorTableEPS0_
 __ZN3JSCL24regExpConstructorDollar7EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
 __ZN3JSCL24regExpConstructorDollar8EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE
index 91a8ce08b9c34d34b503674803e762744cff6379..75737aed66fe43ac0e1d63947b85e129523cbeb2 100644 (file)
@@ -1,99 +1,78 @@
 # JavaScriptCore - Qt4 build info
 VPATH += $$PWD
 
 # JavaScriptCore - Qt4 build info
 VPATH += $$PWD
 
+CONFIG(standalone_package) {
+    isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$PWD/generated
+} else {
+    isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = generated
+}
+
 CONFIG(debug, debug|release) {
 CONFIG(debug, debug|release) {
-    isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = generated$${QMAKE_DIR_SEP}debug
     OBJECTS_DIR = obj/debug
 } else { # Release
     OBJECTS_DIR = obj/debug
 } else { # Release
-    isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = generated$${QMAKE_DIR_SEP}release
     OBJECTS_DIR = obj/release
 }
 
     OBJECTS_DIR = obj/release
 }
 
-INCLUDEPATH += $$GENERATED_SOURCES_DIR \
-               $$PWD \
-               $$PWD/parser \
-               $$PWD/bytecompiler \
-               $$PWD/debugger \
-               $$PWD/runtime \
-               $$PWD/wtf \
-               $$PWD/wtf/unicode \
-               $$PWD/interpreter \
-               $$PWD/jit \
-               $$PWD/profiler \
-               $$PWD/wrec \
-               $$PWD/yarr \
-               $$PWD/API \
-               $$PWD/.. \
-               $$PWD/ForwardingHeaders \
-               $$PWD/bytecode \
-               $$PWD/assembler \
+symbian: {
+    # Need to guarantee this comes before system includes of /epoc32/include
+    MMP_RULES += "USERINCLUDE ../JavaScriptCore/profiler"
+}
+
+INCLUDEPATH = \
+    $$PWD \
+    $$PWD/.. \
+    $$PWD/assembler \
+    $$PWD/bytecode \
+    $$PWD/bytecompiler \
+    $$PWD/debugger \
+    $$PWD/interpreter \
+    $$PWD/jit \
+    $$PWD/parser \
+    $$PWD/pcre \
+    $$PWD/profiler \
+    $$PWD/runtime \
+    $$PWD/wrec \
+    $$PWD/wtf \
+    $$PWD/wtf/unicode \
+    $$PWD/yarr \
+    $$PWD/API \
+    $$PWD/ForwardingHeaders \
+    $$JSC_GENERATED_SOURCES_DIR \
+    $$INCLUDEPATH
 
 DEFINES += BUILDING_QT__ BUILDING_JavaScriptCore BUILDING_WTF
 
 
 DEFINES += BUILDING_QT__ BUILDING_JavaScriptCore BUILDING_WTF
 
-GENERATED_SOURCES_DIR_SLASH = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}
 win32-* {
     LIBS += -lwinmm
 }
 win32-* {
     LIBS += -lwinmm
 }
-
-# Default rules to turn JIT on/off
-!contains(DEFINES, ENABLE_JIT=.) {
-    isEqual(QT_ARCH,i386)|isEqual(QT_ARCH,windows) {
-        # Require gcc >= 4.1
-        CONFIG(release):linux-g++*:greaterThan(QT_GCC_MAJOR_VERSION,3):greaterThan(QT_GCC_MINOR_VERSION,0) {
-            DEFINES += ENABLE_JIT=1
-        }
-        win32-msvc* {
-            DEFINES += ENABLE_JIT=1
-        }
-    }
+contains(JAVASCRIPTCORE_JIT,yes) {
+    DEFINES+=ENABLE_JIT=1
+    DEFINES+=ENABLE_YARR_JIT=1
+    DEFINES+=ENABLE_YARR=1
+}
+contains(JAVASCRIPTCORE_JIT,no) {
+    DEFINES+=ENABLE_JIT=0
+    DEFINES+=ENABLE_YARR_JIT=0
+    DEFINES+=ENABLE_YARR=0
 }
 
 }
 
-# Rules when JIT enabled
-contains(DEFINES, ENABLE_JIT=1) {
-    !contains(DEFINES, ENABLE_YARR=.): DEFINES += ENABLE_YARR=1
-    !contains(DEFINES, ENABLE_YARR_JIT=.): DEFINES += ENABLE_YARR_JIT=1
-    !contains(DEFINES, ENABLE_JIT_OPTIMIZE_CALL=.): DEFINES += ENABLE_JIT_OPTIMIZE_CALL=1
-    !contains(DEFINES, ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS=.): DEFINES += ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS=1
-    !contains(DEFINES, ENABLE_JIT_OPTIMIZE_ARITHMETIC=.): DEFINES += ENABLE_JIT_OPTIMIZE_ARITHMETIC=1
-    linux-g++* {
-        !contains(DEFINES, WTF_USE_JIT_STUB_ARGUMENT_VA_LIST=.): DEFINES += WTF_USE_JIT_STUB_ARGUMENT_VA_LIST=1
+# Rules when JIT enabled (not disabled)
+!contains(DEFINES, ENABLE_JIT=0) {
+    linux*-g++*:greaterThan(QT_GCC_MAJOR_VERSION,3):greaterThan(QT_GCC_MINOR_VERSION,0) {
         QMAKE_CXXFLAGS += -fno-stack-protector
         QMAKE_CFLAGS += -fno-stack-protector
     }
         QMAKE_CXXFLAGS += -fno-stack-protector
         QMAKE_CFLAGS += -fno-stack-protector
     }
-    win32-msvc* {
-        !contains(DEFINES, WTF_USE_JIT_STUB_ARGUMENT_REGISTER=.): DEFINES += WTF_USE_JIT_STUB_ARGUMENT_REGISTER=1
-    }
 }
 
 }
 
-include(pcre/pcre.pri)
-
-LUT_FILES += \
-    runtime/DatePrototype.cpp \
-    runtime/JSONObject.cpp \
-    runtime/NumberConstructor.cpp \
-    runtime/StringPrototype.cpp \
-    runtime/ArrayPrototype.cpp \
-    runtime/MathObject.cpp \
-    runtime/RegExpConstructor.cpp \
-    runtime/RegExpObject.cpp
-
-KEYWORDLUT_FILES += \
-    parser/Keywords.table
+wince* {
+    INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/ce-compat
+    SOURCES += $$QT_SOURCE_TREE/src/3rdparty/ce-compat/ce_time.c
+    DEFINES += WINCEBASIC
+}
 
 
-JSCBISON += \
-    parser/Grammar.y
+include(pcre/pcre.pri)
 
 SOURCES += \
 
 SOURCES += \
-    wtf/Assertions.cpp \
-    wtf/ByteArray.cpp \
-    wtf/HashTable.cpp \
-    wtf/MainThread.cpp \
-    wtf/RandomNumber.cpp \
-    wtf/RefCountedLeakCounter.cpp \
-    wtf/TypeTraits.cpp \
-    wtf/unicode/CollatorDefault.cpp \
-    wtf/unicode/icu/CollatorICU.cpp \
-    wtf/unicode/UTF8.cpp \
     API/JSBase.cpp \
     API/JSCallbackConstructor.cpp \
     API/JSCallbackFunction.cpp \
     API/JSBase.cpp \
     API/JSCallbackConstructor.cpp \
     API/JSCallbackFunction.cpp \
@@ -104,43 +83,39 @@ SOURCES += \
     API/JSStringRef.cpp \
     API/JSValueRef.cpp \
     API/OpaqueJSString.cpp \
     API/JSStringRef.cpp \
     API/JSValueRef.cpp \
     API/OpaqueJSString.cpp \
-    runtime/InitializeThreading.cpp \
-    runtime/JSGlobalData.cpp \
-    runtime/JSGlobalObject.cpp \
-    runtime/JSStaticScopeObject.cpp \
-    runtime/JSVariableObject.cpp \
-    runtime/JSActivation.cpp \
-    runtime/JSNotAnObject.cpp \
-    runtime/JSONObject.cpp \
-    runtime/LiteralParser.cpp \
-    runtime/TimeoutChecker.cpp \
+    assembler/ARMAssembler.cpp \
+    assembler/MacroAssemblerARM.cpp \
     bytecode/CodeBlock.cpp \
     bytecode/CodeBlock.cpp \
-    bytecode/StructureStubInfo.cpp \
     bytecode/JumpTable.cpp \
     bytecode/JumpTable.cpp \
-    jit/JIT.cpp \
-    jit/JITCall.cpp \
+    bytecode/Opcode.cpp \
+    bytecode/SamplingTool.cpp \
+    bytecode/StructureStubInfo.cpp \
+    bytecompiler/BytecodeGenerator.cpp \
+    bytecompiler/NodesCodegen.cpp \
+    debugger/DebuggerActivation.cpp \
+    debugger/DebuggerCallFrame.cpp \
+    debugger/Debugger.cpp \
+    interpreter/CallFrame.cpp \
+    interpreter/Interpreter.cpp \
+    interpreter/RegisterFile.cpp \
+    jit/ExecutableAllocatorPosix.cpp \
+    jit/ExecutableAllocatorSymbian.cpp \
+    jit/ExecutableAllocatorWin.cpp \
+    jit/ExecutableAllocator.cpp \
     jit/JITArithmetic.cpp \
     jit/JITArithmetic.cpp \
+    jit/JITCall.cpp \
+    jit/JIT.cpp \
     jit/JITOpcodes.cpp \
     jit/JITPropertyAccess.cpp \
     jit/JITOpcodes.cpp \
     jit/JITPropertyAccess.cpp \
-    jit/ExecutableAllocator.cpp \
     jit/JITStubs.cpp \
     jit/JITStubs.cpp \
-    bytecompiler/BytecodeGenerator.cpp \
-    runtime/ExceptionHelpers.cpp \
-    runtime/JSPropertyNameIterator.cpp \
-    interpreter/Interpreter.cpp \
-    bytecode/Opcode.cpp \
-    bytecode/SamplingTool.cpp \
-    yarr/RegexCompiler.cpp \
-    yarr/RegexInterpreter.cpp \
-    yarr/RegexJIT.cpp \
-    interpreter/RegisterFile.cpp
-
-win32-*: SOURCES += jit/ExecutableAllocatorWin.cpp
-else: SOURCES += jit/ExecutableAllocatorPosix.cpp
-
-# AllInOneFile.cpp helps gcc analize and optimize code
-# Other compilers may be able to do this at link time
-SOURCES += \
+    parser/Lexer.cpp \
+    parser/Nodes.cpp \
+    parser/ParserArena.cpp \
+    parser/Parser.cpp \
+    profiler/Profile.cpp \
+    profiler/ProfileGenerator.cpp \
+    profiler/ProfileNode.cpp \
+    profiler/Profiler.cpp \
     runtime/ArgList.cpp \
     runtime/Arguments.cpp \
     runtime/ArrayConstructor.cpp \
     runtime/ArgList.cpp \
     runtime/Arguments.cpp \
     runtime/ArrayConstructor.cpp \
@@ -151,60 +126,67 @@ SOURCES += \
     runtime/CallData.cpp \
     runtime/Collector.cpp \
     runtime/CommonIdentifiers.cpp \
     runtime/CallData.cpp \
     runtime/Collector.cpp \
     runtime/CommonIdentifiers.cpp \
+    runtime/Completion.cpp \
     runtime/ConstructData.cpp \
     runtime/ConstructData.cpp \
-    wtf/CurrentTime.cpp \
     runtime/DateConstructor.cpp \
     runtime/DateConversion.cpp \
     runtime/DateInstance.cpp \
     runtime/DatePrototype.cpp \
     runtime/DateConstructor.cpp \
     runtime/DateConversion.cpp \
     runtime/DateInstance.cpp \
     runtime/DatePrototype.cpp \
-    debugger/Debugger.cpp \
-    debugger/DebuggerCallFrame.cpp \
-    debugger/DebuggerActivation.cpp \
-    wtf/dtoa.cpp \
-    runtime/Error.cpp \
     runtime/ErrorConstructor.cpp \
     runtime/ErrorConstructor.cpp \
+    runtime/Error.cpp \
     runtime/ErrorInstance.cpp \
     runtime/ErrorPrototype.cpp \
     runtime/ErrorInstance.cpp \
     runtime/ErrorPrototype.cpp \
-    interpreter/CallFrame.cpp \
+    runtime/ExceptionHelpers.cpp \
+    runtime/Executable.cpp \
     runtime/FunctionConstructor.cpp \
     runtime/FunctionPrototype.cpp \
     runtime/GetterSetter.cpp \
     runtime/GlobalEvalFunction.cpp \
     runtime/Identifier.cpp \
     runtime/FunctionConstructor.cpp \
     runtime/FunctionPrototype.cpp \
     runtime/GetterSetter.cpp \
     runtime/GlobalEvalFunction.cpp \
     runtime/Identifier.cpp \
+    runtime/InitializeThreading.cpp \
     runtime/InternalFunction.cpp \
     runtime/InternalFunction.cpp \
-    runtime/Completion.cpp \
-    runtime/JSArray.cpp \
+    runtime/JSActivation.cpp \
     runtime/JSAPIValueWrapper.cpp \
     runtime/JSAPIValueWrapper.cpp \
+    runtime/JSArray.cpp \
     runtime/JSByteArray.cpp \
     runtime/JSCell.cpp \
     runtime/JSFunction.cpp \
     runtime/JSByteArray.cpp \
     runtime/JSCell.cpp \
     runtime/JSFunction.cpp \
+    runtime/JSGlobalData.cpp \
+    runtime/JSGlobalObject.cpp \
     runtime/JSGlobalObjectFunctions.cpp \
     runtime/JSImmediate.cpp \
     runtime/JSLock.cpp \
     runtime/JSGlobalObjectFunctions.cpp \
     runtime/JSImmediate.cpp \
     runtime/JSLock.cpp \
+    runtime/JSNotAnObject.cpp \
     runtime/JSNumberCell.cpp \
     runtime/JSObject.cpp \
     runtime/JSNumberCell.cpp \
     runtime/JSObject.cpp \
+    runtime/JSONObject.cpp \
+    runtime/JSPropertyNameIterator.cpp \
+    runtime/JSStaticScopeObject.cpp \
     runtime/JSString.cpp \
     runtime/JSValue.cpp \
     runtime/JSString.cpp \
     runtime/JSValue.cpp \
+    runtime/JSVariableObject.cpp \
     runtime/JSWrapperObject.cpp \
     runtime/JSWrapperObject.cpp \
-    parser/Lexer.cpp \
+    runtime/LiteralParser.cpp \
     runtime/Lookup.cpp \
     runtime/Lookup.cpp \
+    runtime/MarkStackPosix.cpp \
+    runtime/MarkStackSymbian.cpp \
+    runtime/MarkStackWin.cpp \
+    runtime/MarkStack.cpp \
     runtime/MathObject.cpp \
     runtime/NativeErrorConstructor.cpp \
     runtime/NativeErrorPrototype.cpp \
     runtime/MathObject.cpp \
     runtime/NativeErrorConstructor.cpp \
     runtime/NativeErrorPrototype.cpp \
-    parser/Nodes.cpp \
     runtime/NumberConstructor.cpp \
     runtime/NumberObject.cpp \
     runtime/NumberPrototype.cpp \
     runtime/ObjectConstructor.cpp \
     runtime/ObjectPrototype.cpp \
     runtime/Operations.cpp \
     runtime/NumberConstructor.cpp \
     runtime/NumberObject.cpp \
     runtime/NumberPrototype.cpp \
     runtime/ObjectConstructor.cpp \
     runtime/ObjectPrototype.cpp \
     runtime/Operations.cpp \
-    parser/Parser.cpp \
-    parser/ParserArena.cpp \
+    runtime/PropertyDescriptor.cpp \
     runtime/PropertyNameArray.cpp \
     runtime/PropertySlot.cpp \
     runtime/PrototypeFunction.cpp \
     runtime/PropertyNameArray.cpp \
     runtime/PropertySlot.cpp \
     runtime/PrototypeFunction.cpp \
-    runtime/RegExp.cpp \
     runtime/RegExpConstructor.cpp \
     runtime/RegExpConstructor.cpp \
+    runtime/RegExp.cpp \
     runtime/RegExpObject.cpp \
     runtime/RegExpPrototype.cpp \
     runtime/ScopeChain.cpp \
     runtime/RegExpObject.cpp \
     runtime/RegExpPrototype.cpp \
     runtime/ScopeChain.cpp \
@@ -212,50 +194,38 @@ SOURCES += \
     runtime/StringConstructor.cpp \
     runtime/StringObject.cpp \
     runtime/StringPrototype.cpp \
     runtime/StringConstructor.cpp \
     runtime/StringObject.cpp \
     runtime/StringPrototype.cpp \
-    runtime/Structure.cpp \
     runtime/StructureChain.cpp \
     runtime/StructureChain.cpp \
+    runtime/Structure.cpp \
+    runtime/TimeoutChecker.cpp \
     runtime/UString.cpp \
     runtime/UString.cpp \
-    profiler/HeavyProfile.cpp \
-    profiler/Profile.cpp \
-    profiler/ProfileGenerator.cpp \
-    profiler/ProfileNode.cpp \
-    profiler/Profiler.cpp \
-    profiler/TreeProfile.cpp \
+    runtime/UStringImpl.cpp \
+    wtf/Assertions.cpp \
+    wtf/ByteArray.cpp \
+    wtf/CurrentTime.cpp \
     wtf/DateMath.cpp \
     wtf/DateMath.cpp \
+    wtf/dtoa.cpp \
     wtf/FastMalloc.cpp \
     wtf/FastMalloc.cpp \
+    wtf/HashTable.cpp \
+    wtf/MainThread.cpp \
+    wtf/qt/MainThreadQt.cpp \
+    wtf/qt/ThreadingQt.cpp \
+    wtf/RandomNumber.cpp \
+    wtf/RefCountedLeakCounter.cpp \
+    wtf/ThreadingNone.cpp \
     wtf/Threading.cpp \
     wtf/Threading.cpp \
-    wtf/qt/MainThreadQt.cpp
-
-!contains(DEFINES, ENABLE_SINGLE_THREADED=1) {
-    SOURCES += wtf/qt/ThreadingQt.cpp
-} else {
-    DEFINES += ENABLE_JSC_MULTIPLE_THREADS=0
-    SOURCES += wtf/ThreadingNone.cpp
-}
-
-# GENERATOR 1-A: LUT creator
-lut.output = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.lut.h
-lut.commands = perl $$PWD/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
-lut.depend = ${QMAKE_FILE_NAME}
-lut.input = LUT_FILES
-lut.CONFIG += no_link
-addExtraCompiler(lut)
+    wtf/TypeTraits.cpp \
+    wtf/unicode/CollatorDefault.cpp \
+    wtf/unicode/icu/CollatorICU.cpp \
+    wtf/unicode/UTF8.cpp \
+    yarr/RegexCompiler.cpp \
+    yarr/RegexInterpreter.cpp \
+    yarr/RegexJIT.cpp
 
 
-# GENERATOR 1-B: particular LUT creator (for 1 file only)
-keywordlut.output = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}Lexer.lut.h
-keywordlut.commands = perl $$PWD/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
-keywordlut.depend = ${QMAKE_FILE_NAME}
-keywordlut.input = KEYWORDLUT_FILES
-keywordlut.CONFIG += no_link
-addExtraCompiler(keywordlut)
+# Generated files, simply list them for JavaScriptCore
+SOURCES += \
+    $${JSC_GENERATED_SOURCES_DIR}/Grammar.cpp
 
 
-# GENERATOR 2: bison grammar
-jscbison.output = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.cpp
-jscbison.commands = bison -d -p jscyy ${QMAKE_FILE_NAME} -o $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.c && $(MOVE) $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.c ${QMAKE_FILE_OUT} && $(MOVE) $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.h $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.h
-jscbison.depend = ${QMAKE_FILE_NAME}
-jscbison.input = JSCBISON
-jscbison.variable_out = GENERATED_SOURCES
-jscbison.dependency_type = TYPE_C
-jscbison.CONFIG = target_predeps
-addExtraCompilerWithHeader(jscbison)
+!contains(DEFINES, USE_SYSTEM_MALLOC) {
+    SOURCES += wtf/TCSystemAlloc.cpp
+}
 
 
index 28f0e6bc45e22c64d0bcda7f4dd1f95e0a89053e..0d6becb2de21ab4a73c97ae758968a3772fcb2a2 100644 (file)
@@ -16,7 +16,6 @@ CONFIG(QTDIR_build) {
     include($$QT_SOURCE_TREE/src/qbase.pri)
     INSTALLS =
     DESTDIR = $$OLDDESTDIR
     include($$QT_SOURCE_TREE/src/qbase.pri)
     INSTALLS =
     DESTDIR = $$OLDDESTDIR
-    PRECOMPILED_HEADER = $$PWD/../WebKit/qt/WebKit_pch.h
     DEFINES *= NDEBUG
 }
 
     DEFINES *= NDEBUG
 }
 
@@ -33,12 +32,6 @@ INCLUDEPATH += $$GENERATED_SOURCES_DIR
     }
 }
 
     }
 }
 
-include($$OUTPUT_DIR/config.pri)
-
-CONFIG -= warn_on
-*-g++*:QMAKE_CXXFLAGS += -Wreturn-type -fno-strict-aliasing
-#QMAKE_CXXFLAGS += -Wall -Wno-undef -Wno-unused-parameter
-
 CONFIG(release):!CONFIG(QTDIR_build) {
     contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
     unix:contains(QT_CONFIG, reduce_relocations):CONFIG += bsymbolic_functions
 CONFIG(release):!CONFIG(QTDIR_build) {
     contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
     unix:contains(QT_CONFIG, reduce_relocations):CONFIG += bsymbolic_functions
@@ -59,17 +52,11 @@ win32-g++ {
     QMAKE_LIBDIR_POST += $$split(TMPPATH,";")
 }
 
     QMAKE_LIBDIR_POST += $$split(TMPPATH,";")
 }
 
-DEFINES += WTF_USE_JAVASCRIPTCORE_BINDINGS=1
-
 DEFINES += WTF_CHANGES=1
 
 include(JavaScriptCore.pri)
 
 QMAKE_EXTRA_TARGETS += generated_files
 
 DEFINES += WTF_CHANGES=1
 
 include(JavaScriptCore.pri)
 
 QMAKE_EXTRA_TARGETS += generated_files
 
-lessThan(QT_MINOR_VERSION, 4) {
-    DEFINES += QT_BEGIN_NAMESPACE="" QT_END_NAMESPACE=""
-}
-
 *-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2
 *-g++*:QMAKE_CXXFLAGS_RELEASE += -O3
 *-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2
 *-g++*:QMAKE_CXXFLAGS_RELEASE += -O3
index 1bdf2510a88cb2a5a8f491833e50e393a84d9838..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,191 +0,0 @@
-<?xml version="1.0" ?>
-<!--
-Copyright (C) 2006, 2007 Kevin Ollivier.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1.  Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-2.  Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Source files for JSCore.
--->
-<makefile>
-    <set append="1" var="JSCORE_API_SOURCES">
-        API/JSBase.cpp
-        API/JSCallbackConstructor.cpp
-        API/JSCallbackFunction.cpp
-        API/JSCallbackObject.cpp
-        API/JSClassRef.cpp
-        API/JSContextRef.cpp
-        API/JSObjectRef.cpp
-        API/JSStringRef.cpp
-        API/JSValueRef.cpp
-        API/OpaqueJSString.cpp
-    </set>
-    <set append="1" var="JSCORE_BYTECOMPILER_SOURCES">
-        bytecompiler/BytecodeGenerator.cpp
-    </set>
-    <set append="1" var="JSCORE_DEBUGGER_SOURCES">
-        debugger/Debugger.cpp
-        debugger/DebuggerActivation.cpp
-        debugger/DebuggerCallFrame.cpp
-    </set>
-    <set append="1" var="JSCORE_JSC_SOURCES">
-        DerivedSources/JavaScriptCore/Grammar.cpp
-        wtf/dtoa.cpp
-    </set>
-    <set append="1" var="JSCORE_PCRE_SOURCES">
-        pcre/pcre_compile.cpp
-        pcre/pcre_exec.cpp
-        pcre/pcre_tables.cpp
-        pcre/pcre_ucp_searchfuncs.cpp
-        pcre/pcre_xclass.cpp
-    </set>
-    <set append="1" var="JSCORE_PARSER_SOURCES">
-        parser/Lexer.cpp
-        parser/Nodes.cpp
-        parser/Parser.cpp
-        parser/ParserArena.cpp
-    </set>
-    <set append="1" var="JSCORE_PROFILER_SOURCES">
-        profiler/HeavyProfile.cpp
-        profiler/ProfileGenerator.cpp
-        profiler/ProfileNode.cpp
-        profiler/Profile.cpp
-        profiler/Profiler.cpp
-        profiler/TreeProfile.cpp
-    </set>
-    <set append="1" var="JSCORE_RUNTIME_SOURCES">
-        runtime/ArgList.cpp
-        runtime/Arguments.cpp
-        runtime/ArrayConstructor.cpp
-        runtime/ArrayPrototype.cpp
-        runtime/BooleanConstructor.cpp
-        runtime/BooleanObject.cpp
-        runtime/BooleanPrototype.cpp
-        runtime/CallData.cpp
-        runtime/Collector.cpp
-        runtime/CommonIdentifiers.cpp
-        runtime/ConstructData.cpp
-        runtime/DateConstructor.cpp
-        runtime/DateConversion.cpp
-        runtime/DateInstance.cpp
-        runtime/DatePrototype.cpp
-        runtime/Error.cpp
-        runtime/ErrorConstructor.cpp
-        runtime/ErrorInstance.cpp
-        runtime/ErrorPrototype.cpp
-        interpreter/CallFrame.cpp
-        runtime/FunctionConstructor.cpp
-        runtime/FunctionPrototype.cpp
-        runtime/GetterSetter.cpp
-        runtime/GlobalEvalFunction.cpp
-        runtime/Identifier.cpp
-        runtime/InitializeThreading.cpp
-        runtime/InternalFunction.cpp
-        runtime/Completion.cpp
-        runtime/JSActivation.cpp
-        runtime/JSArray.cpp
-        runtime/JSByteArray.cpp
-        runtime/JSCell.cpp
-        runtime/JSFunction.cpp
-        runtime/JSGlobalData.cpp
-        runtime/JSGlobalObject.cpp
-        runtime/JSGlobalObjectFunctions.cpp
-        runtime/JSImmediate.cpp
-        runtime/JSLock.cpp
-        runtime/JSNotAnObject.cpp
-        runtime/JSNumberCell.cpp
-        runtime/JSObject.cpp
-        runtime/JSONObject.cpp
-        runtime/JSPropertyNameIterator.cpp
-        runtime/JSStaticScopeObject.cpp
-        runtime/JSString.cpp
-        runtime/JSValue.cpp
-        runtime/JSVariableObject.cpp
-        runtime/JSWrapperObject.cpp
-        runtime/LiteralParser.cpp
-        runtime/Lookup.cpp
-        runtime/MathObject.cpp
-        runtime/NativeErrorConstructor.cpp
-        runtime/NativeErrorPrototype.cpp
-        runtime/NumberConstructor.cpp
-        runtime/NumberObject.cpp
-        runtime/NumberPrototype.cpp
-        runtime/ObjectConstructor.cpp
-        runtime/ObjectPrototype.cpp
-        runtime/Operations.cpp
-        runtime/PropertyNameArray.cpp
-        runtime/PropertySlot.cpp
-        runtime/PrototypeFunction.cpp
-        runtime/RegExp.cpp
-        runtime/RegExpConstructor.cpp
-        runtime/RegExpObject.cpp
-        runtime/RegExpPrototype.cpp
-        runtime/ScopeChain.cpp
-        runtime/SmallStrings.cpp
-        runtime/StringConstructor.cpp
-        runtime/StringObject.cpp
-        runtime/StringPrototype.cpp
-        runtime/Structure.cpp
-        runtime/StructureChain.cpp
-        runtime/UString.cpp
-    </set>
-    <set append="1" var="JSCORE_VM_SOURCES">
-        bytecode/CodeBlock.cpp
-        bytecode/StructureStubInfo.cpp
-        bytecode/JumpTable.cpp
-        runtime/ExceptionHelpers.cpp
-        runtime/TimeoutChecker.cpp
-        interpreter/Interpreter.cpp
-        bytecode/Opcode.cpp
-        bytecode/SamplingTool.cpp
-        interpreter/RegisterFile.cpp
-        jit/ExecutableAllocator.cpp
-    </set>
-    <set append="1" var="JSCORE_VM_SOURCES_WIN">
-       jit/ExecutableAllocatorWin.cpp
-    </set>
-   <set append="1" var="JSCORE_VM_SOURCES_POSIX">
-       jit/ExecutableAllocatorPosix.cpp
-    </set>
-    <set append="1" var="JSCORE_WTF_SOURCES">
-        wtf/Assertions.cpp
-        wtf/ByteArray.cpp
-        wtf/CurrentTime.cpp
-        wtf/DateMath.cpp
-        wtf/FastMalloc.cpp
-        wtf/HashTable.cpp
-        wtf/MainThread.cpp
-        wtf/RandomNumber.cpp
-        wtf/RefCountedLeakCounter.cpp
-        wtf/TCSystemAlloc.cpp
-        wtf/Threading.cpp
-        wtf/ThreadingNone.cpp
-        wtf/TypeTraits.cpp
-        wtf/wx/MainThreadWx.cpp
-        wtf/unicode/CollatorDefault.cpp
-        wtf/unicode/icu/CollatorICU.cpp
-        wtf/unicode/UTF8.cpp
-    </set>
-
-</makefile>
diff --git a/assembler/ARMAssembler.cpp b/assembler/ARMAssembler.cpp
new file mode 100644 (file)
index 0000000..6dd2b87
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2009 University of Szeged
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
+
+#include "ARMAssembler.h"
+
+namespace JSC {
+
+// Patching helpers
+
+void ARMAssembler::patchConstantPoolLoad(void* loadAddr, void* constPoolAddr)
+{
+    ARMWord *ldr = reinterpret_cast<ARMWord*>(loadAddr);
+    ARMWord diff = reinterpret_cast<ARMWord*>(constPoolAddr) - ldr;
+    ARMWord index = (*ldr & 0xfff) >> 1;
+
+    ASSERT(diff >= 1);
+    if (diff >= 2 || index > 0) {
+        diff = (diff + index - 2) * sizeof(ARMWord);
+        ASSERT(diff <= 0xfff);
+        *ldr = (*ldr & ~0xfff) | diff;
+    } else
+        *ldr = (*ldr & ~(0xfff | ARMAssembler::DT_UP)) | sizeof(ARMWord);
+}
+
+// Handle immediates
+
+ARMWord ARMAssembler::getOp2(ARMWord imm)
+{
+    int rol;
+
+    if (imm <= 0xff)
+        return OP2_IMM | imm;
+
+    if ((imm & 0xff000000) == 0) {
+        imm <<= 8;
+        rol = 8;
+    }
+    else {
+        imm = (imm << 24) | (imm >> 8);
+        rol = 0;
+    }
+
+    if ((imm & 0xff000000) == 0) {
+        imm <<= 8;
+        rol += 4;
+    }
+
+    if ((imm & 0xf0000000) == 0) {
+        imm <<= 4;
+        rol += 2;
+    }
+
+    if ((imm & 0xc0000000) == 0) {
+        imm <<= 2;
+        rol += 1;
+    }
+
+    if ((imm & 0x00ffffff) == 0)
+        return OP2_IMM | (imm >> 24) | (rol << 8);
+
+    return INVALID_IMM;
+}
+
+int ARMAssembler::genInt(int reg, ARMWord imm, bool positive)
+{
+    // Step1: Search a non-immediate part
+    ARMWord mask;
+    ARMWord imm1;
+    ARMWord imm2;
+    int rol;
+
+    mask = 0xff000000;
+    rol = 8;
+    while(1) {
+        if ((imm & mask) == 0) {
+            imm = (imm << rol) | (imm >> (32 - rol));
+            rol = 4 + (rol >> 1);
+            break;
+        }
+        rol += 2;
+        mask >>= 2;
+        if (mask & 0x3) {
+            // rol 8
+            imm = (imm << 8) | (imm >> 24);
+            mask = 0xff00;
+            rol = 24;
+            while (1) {
+                if ((imm & mask) == 0) {
+                    imm = (imm << rol) | (imm >> (32 - rol));
+                    rol = (rol >> 1) - 8;
+                    break;
+                }
+                rol += 2;
+                mask >>= 2;
+                if (mask & 0x3)
+                    return 0;
+            }
+            break;
+        }
+    }
+
+    ASSERT((imm & 0xff) == 0);
+
+    if ((imm & 0xff000000) == 0) {
+        imm1 = OP2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8);
+        imm2 = OP2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8);
+    } else if (imm & 0xc0000000) {
+        imm1 = OP2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
+        imm <<= 8;
+        rol += 4;
+
+        if ((imm & 0xff000000) == 0) {
+            imm <<= 8;
+            rol += 4;
+        }
+
+        if ((imm & 0xf0000000) == 0) {
+            imm <<= 4;
+            rol += 2;
+        }
+
+        if ((imm & 0xc0000000) == 0) {
+            imm <<= 2;
+            rol += 1;
+        }
+
+        if ((imm & 0x00ffffff) == 0)
+            imm2 = OP2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
+        else
+            return 0;
+    } else {
+        if ((imm & 0xf0000000) == 0) {
+            imm <<= 4;
+            rol += 2;
+        }
+
+        if ((imm & 0xc0000000) == 0) {
+            imm <<= 2;
+            rol += 1;
+        }
+
+        imm1 = OP2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
+        imm <<= 8;
+        rol += 4;
+
+        if ((imm & 0xf0000000) == 0) {
+            imm <<= 4;
+            rol += 2;
+        }
+
+        if ((imm & 0xc0000000) == 0) {
+            imm <<= 2;
+            rol += 1;
+        }
+
+        if ((imm & 0x00ffffff) == 0)
+            imm2 = OP2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
+        else
+            return 0;
+    }
+
+    if (positive) {
+        mov_r(reg, imm1);
+        orr_r(reg, reg, imm2);
+    } else {
+        mvn_r(reg, imm1);
+        bic_r(reg, reg, imm2);
+    }
+
+    return 1;
+}
+
+ARMWord ARMAssembler::getImm(ARMWord imm, int tmpReg, bool invert)
+{
+    ARMWord tmp;
+
+    // Do it by 1 instruction
+    tmp = getOp2(imm);
+    if (tmp != INVALID_IMM)
+        return tmp;
+
+    tmp = getOp2(~imm);
+    if (tmp != INVALID_IMM) {
+        if (invert)
+            return tmp | OP2_INV_IMM;
+        mvn_r(tmpReg, tmp);
+        return tmpReg;
+    }
+
+    return encodeComplexImm(imm, tmpReg);
+}
+
+void ARMAssembler::moveImm(ARMWord imm, int dest)
+{
+    ARMWord tmp;
+
+    // Do it by 1 instruction
+    tmp = getOp2(imm);
+    if (tmp != INVALID_IMM) {
+        mov_r(dest, tmp);
+        return;
+    }
+
+    tmp = getOp2(~imm);
+    if (tmp != INVALID_IMM) {
+        mvn_r(dest, tmp);
+        return;
+    }
+
+    encodeComplexImm(imm, dest);
+}
+
+ARMWord ARMAssembler::encodeComplexImm(ARMWord imm, int dest)
+{
+#if WTF_ARM_ARCH_AT_LEAST(7)
+    ARMWord tmp = getImm16Op2(imm);
+    if (tmp != INVALID_IMM) {
+        movw_r(dest, tmp);
+        return dest;
+    }
+    movw_r(dest, getImm16Op2(imm & 0xffff));
+    movt_r(dest, getImm16Op2(imm >> 16));
+    return dest;
+#else
+    // Do it by 2 instruction
+    if (genInt(dest, imm, true))
+        return dest;
+    if (genInt(dest, ~imm, false))
+        return dest;
+
+    ldr_imm(dest, imm);
+    return dest;
+#endif
+}
+
+// Memory load/store helpers
+
+void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset)
+{
+    if (offset >= 0) {
+        if (offset <= 0xfff)
+            dtr_u(isLoad, srcDst, base, offset);
+        else if (offset <= 0xfffff) {
+            add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
+            dtr_u(isLoad, srcDst, ARMRegisters::S0, offset & 0xfff);
+        } else {
+            ARMWord reg = getImm(offset, ARMRegisters::S0);
+            dtr_ur(isLoad, srcDst, base, reg);
+        }
+    } else {
+        offset = -offset;
+        if (offset <= 0xfff)
+            dtr_d(isLoad, srcDst, base, offset);
+        else if (offset <= 0xfffff) {
+            sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
+            dtr_d(isLoad, srcDst, ARMRegisters::S0, offset & 0xfff);
+        } else {
+            ARMWord reg = getImm(offset, ARMRegisters::S0);
+            dtr_dr(isLoad, srcDst, base, reg);
+        }
+    }
+}
+
+void ARMAssembler::baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset)
+{
+    ARMWord op2;
+
+    ASSERT(scale >= 0 && scale <= 3);
+    op2 = lsl(index, scale);
+
+    if (offset >= 0 && offset <= 0xfff) {
+        add_r(ARMRegisters::S0, base, op2);
+        dtr_u(isLoad, srcDst, ARMRegisters::S0, offset);
+        return;
+    }
+    if (offset <= 0 && offset >= -0xfff) {
+        add_r(ARMRegisters::S0, base, op2);
+        dtr_d(isLoad, srcDst, ARMRegisters::S0, -offset);
+        return;
+    }
+
+    ldr_un_imm(ARMRegisters::S0, offset);
+    add_r(ARMRegisters::S0, ARMRegisters::S0, op2);
+    dtr_ur(isLoad, srcDst, base, ARMRegisters::S0);
+}
+
+void ARMAssembler::doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset)
+{
+    if (offset & 0x3) {
+        if (offset <= 0x3ff && offset >= 0) {
+            fdtr_u(isLoad, srcDst, base, offset >> 2);
+            return;
+        }
+        if (offset <= 0x3ffff && offset >= 0) {
+            add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 10) | (11 << 8));
+            fdtr_u(isLoad, srcDst, ARMRegisters::S0, (offset >> 2) & 0xff);
+            return;
+        }
+        offset = -offset;
+
+        if (offset <= 0x3ff && offset >= 0) {
+            fdtr_d(isLoad, srcDst, base, offset >> 2);
+            return;
+        }
+        if (offset <= 0x3ffff && offset >= 0) {
+            sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 10) | (11 << 8));
+            fdtr_d(isLoad, srcDst, ARMRegisters::S0, (offset >> 2) & 0xff);
+            return;
+        }
+        offset = -offset;
+    }
+
+    ldr_un_imm(ARMRegisters::S0, offset);
+    add_r(ARMRegisters::S0, ARMRegisters::S0, base);
+    fdtr_u(isLoad, srcDst, ARMRegisters::S0, 0);
+}
+
+void* ARMAssembler::executableCopy(ExecutablePool* allocator)
+{
+    // 64-bit alignment is required for next constant pool and JIT code as well
+    m_buffer.flushWithoutBarrier(true);
+    if (m_buffer.uncheckedSize() & 0x7)
+        bkpt(0);
+
+    char* data = reinterpret_cast<char*>(m_buffer.executableCopy(allocator));
+
+    for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
+        // The last bit is set if the constant must be placed on constant pool.
+        int pos = (*iter) & (~0x1);
+        ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + pos);
+        ARMWord* addr = getLdrImmAddress(ldrAddr);
+        if (*addr != 0xffffffff) {
+            if (!(*iter & 1)) {
+                int diff = reinterpret_cast<ARMWord*>(data + *addr) - (ldrAddr + DefaultPrefetching);
+
+                if ((diff <= BOFFSET_MAX && diff >= BOFFSET_MIN)) {
+                    *ldrAddr = B | getConditionalField(*ldrAddr) | (diff & BRANCH_MASK);
+                    continue;
+                }
+            }
+            *addr = reinterpret_cast<ARMWord>(data + *addr);
+        }
+    }
+
+    return data;
+}
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
diff --git a/assembler/ARMAssembler.h b/assembler/ARMAssembler.h
new file mode 100644 (file)
index 0000000..6967b37
--- /dev/null
@@ -0,0 +1,836 @@
+/*
+ * Copyright (C) 2009 University of Szeged
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ARMAssembler_h
+#define ARMAssembler_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
+
+#include "AssemblerBufferWithConstantPool.h"
+#include <wtf/Assertions.h>
+namespace JSC {
+
+    typedef uint32_t ARMWord;
+
+    namespace ARMRegisters {
+        typedef enum {
+            r0 = 0,
+            r1,
+            r2,
+            r3,
+            S0 = r3,
+            r4,
+            r5,
+            r6,
+            r7,
+            r8,
+            S1 = r8,
+            r9,
+            r10,
+            r11,
+            r12,
+            r13,
+            sp = r13,
+            r14,
+            lr = r14,
+            r15,
+            pc = r15
+        } RegisterID;
+
+        typedef enum {
+            d0,
+            d1,
+            d2,
+            d3,
+            SD0 = d3
+        } FPRegisterID;
+
+    } // namespace ARMRegisters
+
+    class ARMAssembler {
+    public:
+        typedef ARMRegisters::RegisterID RegisterID;
+        typedef ARMRegisters::FPRegisterID FPRegisterID;
+        typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer;
+        typedef SegmentedVector<int, 64> Jumps;
+
+        ARMAssembler() { }
+
+        // ARM conditional constants
+        typedef enum {
+            EQ = 0x00000000, // Zero
+            NE = 0x10000000, // Non-zero
+            CS = 0x20000000,
+            CC = 0x30000000,
+            MI = 0x40000000,
+            PL = 0x50000000,
+            VS = 0x60000000,
+            VC = 0x70000000,
+            HI = 0x80000000,
+            LS = 0x90000000,
+            GE = 0xa0000000,
+            LT = 0xb0000000,
+            GT = 0xc0000000,
+            LE = 0xd0000000,
+            AL = 0xe0000000
+        } Condition;
+
+        // ARM instruction constants
+        enum {
+            AND = (0x0 << 21),
+            EOR = (0x1 << 21),
+            SUB = (0x2 << 21),
+            RSB = (0x3 << 21),
+            ADD = (0x4 << 21),
+            ADC = (0x5 << 21),
+            SBC = (0x6 << 21),
+            RSC = (0x7 << 21),
+            TST = (0x8 << 21),
+            TEQ = (0x9 << 21),
+            CMP = (0xa << 21),
+            CMN = (0xb << 21),
+            ORR = (0xc << 21),
+            MOV = (0xd << 21),
+            BIC = (0xe << 21),
+            MVN = (0xf << 21),
+            MUL = 0x00000090,
+            MULL = 0x00c00090,
+            FADDD = 0x0e300b00,
+            FDIVD = 0x0e800b00,
+            FSUBD = 0x0e300b40,
+            FMULD = 0x0e200b00,
+            FCMPD = 0x0eb40b40,
+            DTR = 0x05000000,
+            LDRH = 0x00100090,
+            STRH = 0x00000090,
+            STMDB = 0x09200000,
+            LDMIA = 0x08b00000,
+            FDTR = 0x0d000b00,
+            B = 0x0a000000,
+            BL = 0x0b000000,
+            FMSR = 0x0e000a10,
+            FMRS = 0x0e100a10,
+            FSITOD = 0x0eb80bc0,
+            FTOSID = 0x0ebd0b40,
+            FMSTAT = 0x0ef1fa10,
+#if WTF_ARM_ARCH_AT_LEAST(5)
+            CLZ = 0x016f0f10,
+            BKPT = 0xe120070,
+#endif
+#if WTF_ARM_ARCH_AT_LEAST(7)
+            MOVW = 0x03000000,
+            MOVT = 0x03400000,
+#endif
+        };
+
+        enum {
+            OP2_IMM = (1 << 25),
+            OP2_IMMh = (1 << 22),
+            OP2_INV_IMM = (1 << 26),
+            SET_CC = (1 << 20),
+            OP2_OFSREG = (1 << 25),
+            DT_UP = (1 << 23),
+            DT_WB = (1 << 21),
+            // This flag is inlcuded in LDR and STR
+            DT_PRE = (1 << 24),
+            HDT_UH = (1 << 5),
+            DT_LOAD = (1 << 20),
+        };
+
+        // Masks of ARM instructions
+        enum {
+            BRANCH_MASK = 0x00ffffff,
+            NONARM = 0xf0000000,
+            SDT_MASK = 0x0c000000,
+            SDT_OFFSET_MASK = 0xfff,
+        };
+
+        enum {
+            BOFFSET_MIN = -0x00800000,
+            BOFFSET_MAX = 0x007fffff,
+            SDT = 0x04000000,
+        };
+
+        enum {
+            padForAlign8  = 0x00,
+            padForAlign16 = 0x0000,
+            padForAlign32 = 0xee120070,
+        };
+
+        static const ARMWord INVALID_IMM = 0xf0000000;
+        static const int DefaultPrefetching = 2;
+
+        class JmpSrc {
+            friend class ARMAssembler;
+        public:
+            JmpSrc()
+                : m_offset(-1)
+            {
+            }
+
+        private:
+            JmpSrc(int offset)
+                : m_offset(offset)
+            {
+            }
+
+            int m_offset;
+        };
+
+        class JmpDst {
+            friend class ARMAssembler;
+        public:
+            JmpDst()
+                : m_offset(-1)
+                , m_used(false)
+            {
+            }
+
+            bool isUsed() const { return m_used; }
+            void used() { m_used = true; }
+        private:
+            JmpDst(int offset)
+                : m_offset(offset)
+                , m_used(false)
+            {
+                ASSERT(m_offset == offset);
+            }
+
+            int m_offset : 31;
+            int m_used : 1;
+        };
+
+        // Instruction formating
+
+        void emitInst(ARMWord op, int rd, int rn, ARMWord op2)
+        {
+            ASSERT ( ((op2 & ~OP2_IMM) <= 0xfff) || (((op2 & ~OP2_IMMh) <= 0xfff)) );
+            m_buffer.putInt(op | RN(rn) | RD(rd) | op2);
+        }
+
+        void and_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | AND, rd, rn, op2);
+        }
+
+        void ands_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | AND | SET_CC, rd, rn, op2);
+        }
+
+        void eor_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | EOR, rd, rn, op2);
+        }
+
+        void eors_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | EOR | SET_CC, rd, rn, op2);
+        }
+
+        void sub_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | SUB, rd, rn, op2);
+        }
+
+        void subs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | SUB | SET_CC, rd, rn, op2);
+        }
+
+        void rsb_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | RSB, rd, rn, op2);
+        }
+
+        void rsbs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | RSB | SET_CC, rd, rn, op2);
+        }
+
+        void add_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | ADD, rd, rn, op2);
+        }
+
+        void adds_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | ADD | SET_CC, rd, rn, op2);
+        }
+
+        void adc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | ADC, rd, rn, op2);
+        }
+
+        void adcs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | ADC | SET_CC, rd, rn, op2);
+        }
+
+        void sbc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | SBC, rd, rn, op2);
+        }
+
+        void sbcs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | SBC | SET_CC, rd, rn, op2);
+        }
+
+        void rsc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | RSC, rd, rn, op2);
+        }
+
+        void rscs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | RSC | SET_CC, rd, rn, op2);
+        }
+
+        void tst_r(int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | TST | SET_CC, 0, rn, op2);
+        }
+
+        void teq_r(int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | TEQ | SET_CC, 0, rn, op2);
+        }
+
+        void cmp_r(int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2);
+        }
+
+        void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2);
+        }
+
+        void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | ORR | SET_CC, rd, rn, op2);
+        }
+
+        void mov_r(int rd, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | MOV, rd, ARMRegisters::r0, op2);
+        }
+
+#if WTF_ARM_ARCH_AT_LEAST(7)
+        void movw_r(int rd, ARMWord op2, Condition cc = AL)
+        {
+            ASSERT((op2 | 0xf0fff) == 0xf0fff);
+            m_buffer.putInt(static_cast<ARMWord>(cc) | MOVW | RD(rd) | op2);
+        }
+
+        void movt_r(int rd, ARMWord op2, Condition cc = AL)
+        {
+            ASSERT((op2 | 0xf0fff) == 0xf0fff);
+            m_buffer.putInt(static_cast<ARMWord>(cc) | MOVT | RD(rd) | op2);
+        }
+#endif
+
+        void movs_r(int rd, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | MOV | SET_CC, rd, ARMRegisters::r0, op2);
+        }
+
+        void bic_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | BIC, rd, rn, op2);
+        }
+
+        void bics_r(int rd, int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | BIC | SET_CC, rd, rn, op2);
+        }
+
+        void mvn_r(int rd, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | MVN, rd, ARMRegisters::r0, op2);
+        }
+
+        void mvns_r(int rd, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | MVN | SET_CC, rd, ARMRegisters::r0, op2);
+        }
+
+        void mul_r(int rd, int rn, int rm, Condition cc = AL)
+        {
+            m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | RN(rd) | RS(rn) | RM(rm));
+        }
+
+        void muls_r(int rd, int rn, int rm, Condition cc = AL)
+        {
+            m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | SET_CC | RN(rd) | RS(rn) | RM(rm));
+        }
+
+        void mull_r(int rdhi, int rdlo, int rn, int rm, Condition cc = AL)
+        {
+            m_buffer.putInt(static_cast<ARMWord>(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm));
+        }
+
+        void faddd_r(int dd, int dn, int dm, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | FADDD, dd, dn, dm);
+        }
+
+        void fdivd_r(int dd, int dn, int dm, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | FDIVD, dd, dn, dm);
+        }
+
+        void fsubd_r(int dd, int dn, int dm, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | FSUBD, dd, dn, dm);
+        }
+
+        void fmuld_r(int dd, int dn, int dm, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | FMULD, dd, dn, dm);
+        }
+
+        void fcmpd_r(int dd, int dm, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | FCMPD, dd, 0, dm);
+        }
+
+        void ldr_imm(int rd, ARMWord imm, Condition cc = AL)
+        {
+            m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm, true);
+        }
+
+        void ldr_un_imm(int rd, ARMWord imm, Condition cc = AL)
+        {
+            m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm);
+        }
+
+        void dtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP, rd, rb, op2);
+        }
+
+        void dtr_ur(bool isLoad, int rd, int rb, int rm, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP | OP2_OFSREG, rd, rb, rm);
+        }
+
+        void dtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0), rd, rb, op2);
+        }
+
+        void dtr_dr(bool isLoad, int rd, int rb, int rm, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | OP2_OFSREG, rd, rb, rm);
+        }
+
+        void ldrh_r(int rd, int rn, int rm, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm);
+        }
+
+        void ldrh_d(int rd, int rb, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_PRE, rd, rb, op2);
+        }
+
+        void ldrh_u(int rd, int rb, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rb, op2);
+        }
+
+        void strh_r(int rn, int rm, int rd, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | STRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm);
+        }
+
+        void fdtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
+        {
+            ASSERT(op2 <= 0xff);
+            emitInst(static_cast<ARMWord>(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), rd, rb, op2);
+        }
+
+        void fdtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
+        {
+            ASSERT(op2 <= 0xff);
+            emitInst(static_cast<ARMWord>(cc) | FDTR | (isLoad ? DT_LOAD : 0), rd, rb, op2);
+        }
+
+        void push_r(int reg, Condition cc = AL)
+        {
+            ASSERT(ARMWord(reg) <= 0xf);
+            m_buffer.putInt(cc | DTR | DT_WB | RN(ARMRegisters::sp) | RD(reg) | 0x4);
+        }
+
+        void pop_r(int reg, Condition cc = AL)
+        {
+            ASSERT(ARMWord(reg) <= 0xf);
+            m_buffer.putInt(cc | (DTR ^ DT_PRE) | DT_LOAD | DT_UP | RN(ARMRegisters::sp) | RD(reg) | 0x4);
+        }
+
+        inline void poke_r(int reg, Condition cc = AL)
+        {
+            dtr_d(false, ARMRegisters::sp, 0, reg, cc);
+        }
+
+        inline void peek_r(int reg, Condition cc = AL)
+        {
+            dtr_u(true, reg, ARMRegisters::sp, 0, cc);
+        }
+
+        void fmsr_r(int dd, int rn, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | FMSR, rn, dd, 0);
+        }
+
+        void fmrs_r(int rd, int dn, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | FMRS, rd, dn, 0);
+        }
+
+        void fsitod_r(int dd, int dm, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | FSITOD, dd, 0, dm);
+        }
+
+        void ftosid_r(int fd, int dm, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | FTOSID, fd, 0, dm);
+        }
+
+        void fmstat(Condition cc = AL)
+        {
+            m_buffer.putInt(static_cast<ARMWord>(cc) | FMSTAT);
+        }
+
+#if WTF_ARM_ARCH_AT_LEAST(5)
+        void clz_r(int rd, int rm, Condition cc = AL)
+        {
+            m_buffer.putInt(static_cast<ARMWord>(cc) | CLZ | RD(rd) | RM(rm));
+        }
+#endif
+
+        void bkpt(ARMWord value)
+        {
+#if WTF_ARM_ARCH_AT_LEAST(5)
+            m_buffer.putInt(BKPT | ((value & 0xff0) << 4) | (value & 0xf));
+#else
+            // Cannot access to Zero memory address
+            dtr_dr(true, ARMRegisters::S0, ARMRegisters::S0, ARMRegisters::S0);
+#endif
+        }
+
+        static ARMWord lsl(int reg, ARMWord value)
+        {
+            ASSERT(reg <= ARMRegisters::pc);
+            ASSERT(value <= 0x1f);
+            return reg | (value << 7) | 0x00;
+        }
+
+        static ARMWord lsr(int reg, ARMWord value)
+        {
+            ASSERT(reg <= ARMRegisters::pc);
+            ASSERT(value <= 0x1f);
+            return reg | (value << 7) | 0x20;
+        }
+
+        static ARMWord asr(int reg, ARMWord value)
+        {
+            ASSERT(reg <= ARMRegisters::pc);
+            ASSERT(value <= 0x1f);
+            return reg | (value << 7) | 0x40;
+        }
+
+        static ARMWord lsl_r(int reg, int shiftReg)
+        {
+            ASSERT(reg <= ARMRegisters::pc);
+            ASSERT(shiftReg <= ARMRegisters::pc);
+            return reg | (shiftReg << 8) | 0x10;
+        }
+
+        static ARMWord lsr_r(int reg, int shiftReg)
+        {
+            ASSERT(reg <= ARMRegisters::pc);
+            ASSERT(shiftReg <= ARMRegisters::pc);
+            return reg | (shiftReg << 8) | 0x30;
+        }
+
+        static ARMWord asr_r(int reg, int shiftReg)
+        {
+            ASSERT(reg <= ARMRegisters::pc);
+            ASSERT(shiftReg <= ARMRegisters::pc);
+            return reg | (shiftReg << 8) | 0x50;
+        }
+
+        // General helpers
+
+        int size()
+        {
+            return m_buffer.size();
+        }
+
+        void ensureSpace(int insnSpace, int constSpace)
+        {
+            m_buffer.ensureSpace(insnSpace, constSpace);
+        }
+
+        int sizeOfConstantPool()
+        {
+            return m_buffer.sizeOfConstantPool();
+        }
+
+        JmpDst label()
+        {
+            return JmpDst(m_buffer.size());
+        }
+
+        JmpDst align(int alignment)
+        {
+            while (!m_buffer.isAligned(alignment))
+                mov_r(ARMRegisters::r0, ARMRegisters::r0);
+
+            return label();
+        }
+
+        JmpSrc jmp(Condition cc = AL, int useConstantPool = 0)
+        {
+            ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
+            int s = m_buffer.uncheckedSize();
+            ldr_un_imm(ARMRegisters::pc, 0xffffffff, cc);
+            m_jumps.append(s | (useConstantPool & 0x1));
+            return JmpSrc(s);
+        }
+
+        void* executableCopy(ExecutablePool* allocator);
+
+        // Patching helpers
+
+        static ARMWord* getLdrImmAddress(ARMWord* insn)
+        {
+            // Must be an ldr ..., [pc +/- imm]
+            ASSERT((*insn & 0x0f7f0000) == 0x051f0000);
+
+            ARMWord addr = reinterpret_cast<ARMWord>(insn) + DefaultPrefetching * sizeof(ARMWord);
+            if (*insn & DT_UP)
+                return reinterpret_cast<ARMWord*>(addr + (*insn & SDT_OFFSET_MASK));
+            return reinterpret_cast<ARMWord*>(addr - (*insn & SDT_OFFSET_MASK));
+        }
+
+        static ARMWord* getLdrImmAddressOnPool(ARMWord* insn, uint32_t* constPool)
+        {
+            // Must be an ldr ..., [pc +/- imm]
+            ASSERT((*insn & 0x0f7f0000) == 0x051f0000);
+
+            if (*insn & 0x1)
+                return reinterpret_cast<ARMWord*>(constPool + ((*insn & SDT_OFFSET_MASK) >> 1));
+            return getLdrImmAddress(insn);
+        }
+
+        static void patchPointerInternal(intptr_t from, void* to)
+        {
+            ARMWord* insn = reinterpret_cast<ARMWord*>(from);
+            ARMWord* addr = getLdrImmAddress(insn);
+            *addr = reinterpret_cast<ARMWord>(to);
+        }
+
+        static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value)
+        {
+            value = (value << 1) + 1;
+            ASSERT(!(value & ~0xfff));
+            return (load & ~0xfff) | value;
+        }
+
+        static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr);
+
+        // Patch pointers
+
+        static void linkPointer(void* code, JmpDst from, void* to)
+        {
+            patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
+        }
+
+        static void repatchInt32(void* from, int32_t to)
+        {
+            patchPointerInternal(reinterpret_cast<intptr_t>(from), reinterpret_cast<void*>(to));
+        }
+
+        static void repatchPointer(void* from, void* to)
+        {
+            patchPointerInternal(reinterpret_cast<intptr_t>(from), to);
+        }
+
+        static void repatchLoadPtrToLEA(void* from)
+        {
+            // On arm, this is a patch from LDR to ADD. It is restricted conversion,
+            // from special case to special case, altough enough for its purpose
+            ARMWord* insn = reinterpret_cast<ARMWord*>(from);
+            ASSERT((*insn & 0x0ff00f00) == 0x05900000);
+
+            *insn = (*insn & 0xf00ff0ff) | 0x02800000;
+            ExecutableAllocator::cacheFlush(insn, sizeof(ARMWord));
+        }
+
+        // Linkers
+
+        void linkJump(JmpSrc from, JmpDst to)
+        {
+            ARMWord* insn = reinterpret_cast<ARMWord*>(m_buffer.data()) + (from.m_offset / sizeof(ARMWord));
+            ARMWord* addr = getLdrImmAddressOnPool(insn, m_buffer.poolAddress());
+            *addr = static_cast<ARMWord>(to.m_offset);
+        }
+
+        static void linkJump(void* code, JmpSrc from, void* to)
+        {
+            patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
+        }
+
+        static void relinkJump(void* from, void* to)
+        {
+            patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
+        }
+
+        static void linkCall(void* code, JmpSrc from, void* to)
+        {
+            patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
+        }
+
+        static void relinkCall(void* from, void* to)
+        {
+            patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
+        }
+
+        // Address operations
+
+        static void* getRelocatedAddress(void* code, JmpSrc jump)
+        {
+            return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + jump.m_offset / sizeof(ARMWord) + 1);
+        }
+
+        static void* getRelocatedAddress(void* code, JmpDst label)
+        {
+            return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + label.m_offset / sizeof(ARMWord));
+        }
+
+        // Address differences
+
+        static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to)
+        {
+            return (to.m_offset + sizeof(ARMWord)) - from.m_offset;
+        }
+
+        static int getDifferenceBetweenLabels(JmpDst from, JmpDst to)
+        {
+            return to.m_offset - from.m_offset;
+        }
+
+        static unsigned getCallReturnOffset(JmpSrc call)
+        {
+            return call.m_offset + sizeof(ARMWord);
+        }
+
+        // Handle immediates
+
+        static ARMWord getOp2Byte(ARMWord imm)
+        {
+            ASSERT(imm <= 0xff);
+            return OP2_IMMh | (imm & 0x0f) | ((imm & 0xf0) << 4) ;
+        }
+
+        static ARMWord getOp2(ARMWord imm);
+
+#if WTF_ARM_ARCH_AT_LEAST(7)
+        static ARMWord getImm16Op2(ARMWord imm)
+        {
+            if (imm <= 0xffff)
+                return (imm & 0xf000) << 4 | (imm & 0xfff);
+            return INVALID_IMM;
+        }
+#endif
+        ARMWord getImm(ARMWord imm, int tmpReg, bool invert = false);
+        void moveImm(ARMWord imm, int dest);
+        ARMWord encodeComplexImm(ARMWord imm, int dest);
+
+        // Memory load/store helpers
+
+        void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset);
+        void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset);
+        void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset);
+
+        // Constant pool hnadlers
+
+        static ARMWord placeConstantPoolBarrier(int offset)
+        {
+            offset = (offset - sizeof(ARMWord)) >> 2;
+            ASSERT((offset <= BOFFSET_MAX && offset >= BOFFSET_MIN));
+            return AL | B | (offset & BRANCH_MASK);
+        }
+
+    private:
+        ARMWord RM(int reg)
+        {
+            ASSERT(reg <= ARMRegisters::pc);
+            return reg;
+        }
+
+        ARMWord RS(int reg)
+        {
+            ASSERT(reg <= ARMRegisters::pc);
+            return reg << 8;
+        }
+
+        ARMWord RD(int reg)
+        {
+            ASSERT(reg <= ARMRegisters::pc);
+            return reg << 12;
+        }
+
+        ARMWord RN(int reg)
+        {
+            ASSERT(reg <= ARMRegisters::pc);
+            return reg << 16;
+        }
+
+        static ARMWord getConditionalField(ARMWord i)
+        {
+            return i & 0xf0000000;
+        }
+
+        int genInt(int reg, ARMWord imm, bool positive);
+
+        ARMBuffer m_buffer;
+        Jumps m_jumps;
+    };
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
+
+#endif // ARMAssembler_h
index 7cf88736c74923c93ba15a727a5a92a2437a74ec..4e394b2069246ade02dd8adac9b197c072939cc9 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <wtf/Platform.h>
 
 
 #include <wtf/Platform.h>
 
-#if ENABLE(ASSEMBLER) && PLATFORM_ARM_ARCH(7)
+#if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
 
 #include "AssemblerBuffer.h"
 #include <wtf/Assertions.h>
 
 #include "AssemblerBuffer.h"
 #include <wtf/Assertions.h>
@@ -37,7 +37,7 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
-namespace ARM {
+namespace ARMRegisters {
     typedef enum {
         r0,
         r1,
     typedef enum {
         r0,
         r1,
@@ -199,12 +199,12 @@ class ARMThumbImmediate {
         };
     } PatternBytes;
 
         };
     } PatternBytes;
 
-    ALWAYS_INLINE static int32_t countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
+    ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
     {
     {
-        if (value & ~((1<<N)-1)) /* check for any of the top N bits (of 2N bits) are set */ \
-            value >>= N;         /* if any were set, lose the bottom N */ \
-        else                     /* if none of the top N bits are set, */ \
-            zeros += N;          /* then we have identified N leading zeros */
+        if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */
+            value >>= N;             /* if any were set, lose the bottom N */
+        else                         /* if none of the top N bits are set, */
+            zeros += N;              /* then we have identified N leading zeros */
     }
 
     static int32_t countLeadingZeros(uint32_t value)
     }
 
     static int32_t countLeadingZeros(uint32_t value)
@@ -236,6 +236,11 @@ class ARMThumbImmediate {
     ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
         : m_type(TypeUInt16)
     {
     ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
         : m_type(TypeUInt16)
     {
+        // Make sure this constructor is only reached with type TypeUInt16;
+        // this extra parameter makes the code a little clearer by making it
+        // explicit at call sites which type is being constructed
+        ASSERT_UNUSED(type, type == TypeUInt16);
+
         m_value.asInt = value;
     }
 
         m_value.asInt = value;
     }
 
@@ -407,8 +412,13 @@ register writeback
 
 class ARMv7Assembler {
 public:
 
 class ARMv7Assembler {
 public:
-    typedef ARM::RegisterID RegisterID;
-    typedef ARM::FPRegisterID FPRegisterID;
+    ~ARMv7Assembler()
+    {
+        ASSERT(m_jumpsToLink.isEmpty());
+    }
+
+    typedef ARMRegisters::RegisterID RegisterID;
+    typedef ARMRegisters::FPRegisterID FPRegisterID;
 
     // (HS, LO, HI, LS) -> (AE, B, A, BE)
     // (VS, VC) -> (O, NO)
 
     // (HS, LO, HI, LS) -> (AE, B, A, BE)
     // (VS, VC) -> (O, NO)
@@ -477,10 +487,21 @@ public:
 
 private:
 
 
 private:
 
+    struct LinkRecord {
+        LinkRecord(intptr_t from, intptr_t to)
+            : from(from)
+            , to(to)
+        {
+        }
+
+        intptr_t from;
+        intptr_t to;
+    };
+
     // ARMv7, Appx-A.6.3
     bool BadReg(RegisterID reg)
     {
     // ARMv7, Appx-A.6.3
     bool BadReg(RegisterID reg)
     {
-        return (reg == ARM::sp) || (reg == ARM::pc);
+        return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
     }
 
     bool isSingleRegister(FPRegisterID reg)
     }
 
     bool isSingleRegister(FPRegisterID reg)
@@ -574,6 +595,7 @@ private:
         OP_SUB_SP_imm_T1    = 0xB080,
         OP_BKPT             = 0xBE00,
         OP_IT               = 0xBF00,
         OP_SUB_SP_imm_T1    = 0xB080,
         OP_BKPT             = 0xBE00,
         OP_IT               = 0xBF00,
+        OP_NOP_T1           = 0xBF00,
     } OpcodeID;
 
     typedef enum {
     } OpcodeID;
 
     typedef enum {
@@ -608,6 +630,7 @@ private:
         OP_MOV_imm_T3   = 0xF240,
         OP_SUB_imm_T4   = 0xF2A0,
         OP_MOVT         = 0xF2C0,
         OP_MOV_imm_T3   = 0xF240,
         OP_SUB_imm_T4   = 0xF2A0,
         OP_MOVT         = 0xF2C0,
+        OP_NOP_T2a      = 0xF3AF,
         OP_LDRH_reg_T2  = 0xF830,
         OP_LDRH_imm_T3  = 0xF830,
         OP_STR_imm_T4   = 0xF840,
         OP_LDRH_reg_T2  = 0xF830,
         OP_LDRH_imm_T3  = 0xF830,
         OP_STR_imm_T4   = 0xF840,
@@ -626,6 +649,7 @@ private:
 
     typedef enum {
         OP_B_T4b        = 0x9000,
 
     typedef enum {
         OP_B_T4b        = 0x9000,
+        OP_NOP_T2b      = 0x8000,
     } OpcodeID2;
 
     struct FourFours {
     } OpcodeID2;
 
     struct FourFours {
@@ -692,16 +716,16 @@ public:
     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
-        ASSERT((rd != ARM::sp) || (rn == ARM::sp));
-        ASSERT(rd != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
+        ASSERT(rd != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isValid());
 
         ASSERT(imm.isValid());
 
-        if (rn == ARM::sp) {
+        if (rn == ARMRegisters::sp) {
             if (!(rd & 8) && imm.isUInt10()) {
                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
                 return;
             if (!(rd & 8) && imm.isUInt10()) {
                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
                 return;
-            } else if ((rd == ARM::sp) && imm.isUInt9()) {
+            } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
                 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
                 return;
             }
                 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
                 return;
             }
@@ -725,9 +749,9 @@ public:
 
     void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
 
     void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
-        ASSERT((rd != ARM::sp) || (rn == ARM::sp));
-        ASSERT(rd != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
+        ASSERT(rd != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
@@ -749,9 +773,9 @@ public:
     void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
     void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
-        ASSERT((rd != ARM::sp) || (rn == ARM::sp));
-        ASSERT(rd != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
+        ASSERT(rd != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isEncodedImm());
 
         if (!((rd | rn) & 8)) {
         ASSERT(imm.isEncodedImm());
 
         if (!((rd | rn) & 8)) {
@@ -770,9 +794,9 @@ public:
     // Not allowed in an IT (if then) block?
     void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
     // Not allowed in an IT (if then) block?
     void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
-        ASSERT((rd != ARM::sp) || (rn == ARM::sp));
-        ASSERT(rd != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
+        ASSERT(rd != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
@@ -838,7 +862,7 @@ public:
     // Only allowed in IT (if then) block if last instruction.
     JmpSrc blx(RegisterID rm)
     {
     // Only allowed in IT (if then) block if last instruction.
     JmpSrc blx(RegisterID rm)
     {
-        ASSERT(rm != ARM::pc);
+        ASSERT(rm != ARMRegisters::pc);
         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
         return JmpSrc(m_formatter.size());
     }
         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
         return JmpSrc(m_formatter.size());
     }
@@ -857,7 +881,7 @@ public:
 
     void cmn(RegisterID rn, ARMThumbImmediate imm)
     {
 
     void cmn(RegisterID rn, ARMThumbImmediate imm)
     {
-        ASSERT(rn != ARM::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isEncodedImm());
 
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
         ASSERT(imm.isEncodedImm());
 
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
@@ -865,7 +889,7 @@ public:
 
     void cmp(RegisterID rn, ARMThumbImmediate imm)
     {
 
     void cmp(RegisterID rn, ARMThumbImmediate imm)
     {
-        ASSERT(rn != ARM::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isEncodedImm());
 
         if (!(rn & 8) && imm.isUInt8())
         ASSERT(imm.isEncodedImm());
 
         if (!(rn & 8) && imm.isUInt8())
@@ -876,7 +900,7 @@ public:
 
     void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
 
     void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
-        ASSERT(rn != ARM::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
     }
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
     }
@@ -938,15 +962,15 @@ public:
         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
     }
 
         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
     }
 
-    // rt == ARM::pc only allowed if last instruction in IT (if then) block.
+    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
     void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
     {
     void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
     {
-        ASSERT(rn != ARM::pc); // LDR (literal)
+        ASSERT(rn != ARMRegisters::pc); // LDR (literal)
         ASSERT(imm.isUInt12());
 
         if (!((rt | rn) & 8) && imm.isUInt7())
             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
         ASSERT(imm.isUInt12());
 
         if (!((rt | rn) & 8) && imm.isUInt7())
             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
-        else if ((rn == ARM::sp) && !(rt & 8) && imm.isUInt10())
+        else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
             m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
         else
             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
             m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
         else
             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
@@ -965,8 +989,8 @@ public:
     // if (wback) REG[rn] = _tmp
     void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
     {
     // if (wback) REG[rn] = _tmp
     void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
     {
-        ASSERT(rt != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT(rt != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(index || wback);
         ASSERT(!wback | (rt != rn));
     
         ASSERT(index || wback);
         ASSERT(!wback | (rt != rn));
     
@@ -985,10 +1009,10 @@ public:
         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
     }
 
         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
     }
 
-    // rt == ARM::pc only allowed if last instruction in IT (if then) block.
+    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
     void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
     {
     void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
     {
-        ASSERT(rn != ARM::pc); // LDR (literal)
+        ASSERT(rn != ARMRegisters::pc); // LDR (literal)
         ASSERT(!BadReg(rm));
         ASSERT(shift <= 3);
 
         ASSERT(!BadReg(rm));
         ASSERT(shift <= 3);
 
@@ -998,10 +1022,10 @@ public:
             m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
     }
 
             m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
     }
 
-    // rt == ARM::pc only allowed if last instruction in IT (if then) block.
+    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
     void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
     {
     void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
     {
-        ASSERT(rn != ARM::pc); // LDR (literal)
+        ASSERT(rn != ARMRegisters::pc); // LDR (literal)
         ASSERT(imm.isUInt12());
 
         if (!((rt | rn) & 8) && imm.isUInt6())
         ASSERT(imm.isUInt12());
 
         if (!((rt | rn) & 8) && imm.isUInt6())
@@ -1023,8 +1047,8 @@ public:
     // if (wback) REG[rn] = _tmp
     void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
     {
     // if (wback) REG[rn] = _tmp
     void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
     {
-        ASSERT(rt != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT(rt != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(index || wback);
         ASSERT(!wback | (rt != rn));
     
         ASSERT(index || wback);
         ASSERT(!wback | (rt != rn));
     
@@ -1046,7 +1070,7 @@ public:
     void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
     {
         ASSERT(!BadReg(rt));   // Memory hint
     void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
     {
         ASSERT(!BadReg(rt));   // Memory hint
-        ASSERT(rn != ARM::pc); // LDRH (literal)
+        ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
         ASSERT(!BadReg(rm));
         ASSERT(shift <= 3);
 
         ASSERT(!BadReg(rm));
         ASSERT(shift <= 3);
 
@@ -1197,16 +1221,16 @@ public:
         m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
     }
 
         m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
     }
 
-    // rt == ARM::pc only allowed if last instruction in IT (if then) block.
+    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
     void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
     {
     void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
     {
-        ASSERT(rt != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT(rt != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isUInt12());
 
         if (!((rt | rn) & 8) && imm.isUInt7())
             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
         ASSERT(imm.isUInt12());
 
         if (!((rt | rn) & 8) && imm.isUInt7())
             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
-        else if ((rn == ARM::sp) && !(rt & 8) && imm.isUInt10())
+        else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
             m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
         else
             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
             m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
         else
             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
@@ -1225,8 +1249,8 @@ public:
     // if (wback) REG[rn] = _tmp
     void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
     {
     // if (wback) REG[rn] = _tmp
     void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
     {
-        ASSERT(rt != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT(rt != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(index || wback);
         ASSERT(!wback | (rt != rn));
     
         ASSERT(index || wback);
         ASSERT(!wback | (rt != rn));
     
@@ -1245,10 +1269,10 @@ public:
         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
     }
 
         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
     }
 
-    // rt == ARM::pc only allowed if last instruction in IT (if then) block.
+    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
     void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
     {
     void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
     {
-        ASSERT(rn != ARM::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(!BadReg(rm));
         ASSERT(shift <= 3);
 
         ASSERT(!BadReg(rm));
         ASSERT(shift <= 3);
 
@@ -1261,12 +1285,12 @@ public:
     void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
     void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
-        ASSERT((rd != ARM::sp) || (rn == ARM::sp));
-        ASSERT(rd != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
+        ASSERT(rd != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isValid());
 
         ASSERT(imm.isValid());
 
-        if ((rn == ARM::sp) && (rd == ARM::sp) && imm.isUInt9()) {
+        if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
             return;
         } else if (!((rd | rn) & 8)) {
             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
             return;
         } else if (!((rd | rn) & 8)) {
@@ -1289,9 +1313,9 @@ public:
 
     void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
 
     void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
-        ASSERT((rd != ARM::sp) || (rn == ARM::sp));
-        ASSERT(rd != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
+        ASSERT(rd != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
@@ -1309,12 +1333,12 @@ public:
     void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
     void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
-        ASSERT((rd != ARM::sp) || (rn == ARM::sp));
-        ASSERT(rd != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
+        ASSERT(rd != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isValid());
 
         ASSERT(imm.isValid());
 
-        if ((rn == ARM::sp) && (rd == ARM::sp) && imm.isUInt9()) {
+        if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
             return;
         } else if (!((rd | rn) & 8)) {
             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
             return;
         } else if (!((rd | rn) & 8)) {
@@ -1333,9 +1357,9 @@ public:
     // Not allowed in an IT (if then) block?
     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
     // Not allowed in an IT (if then) block?
     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
-        ASSERT((rd != ARM::sp) || (rn == ARM::sp));
-        ASSERT(rd != ARM::pc);
-        ASSERT(rn != ARM::pc);
+        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
+        ASSERT(rd != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
@@ -1481,6 +1505,15 @@ public:
     void* executableCopy(ExecutablePool* allocator)
     {
         void* copy = m_formatter.executableCopy(allocator);
     void* executableCopy(ExecutablePool* allocator)
     {
         void* copy = m_formatter.executableCopy(allocator);
+
+        unsigned jumpCount = m_jumpsToLink.size();
+        for (unsigned i = 0; i < jumpCount; ++i) {
+            uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].from);
+            uint16_t* target = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].to);
+            linkJumpAbsolute(location, target);
+        }
+        m_jumpsToLink.clear();
+
         ASSERT(copy);
         return copy;
     }
         ASSERT(copy);
         return copy;
     }
@@ -1503,11 +1536,7 @@ public:
     {
         ASSERT(to.m_offset != -1);
         ASSERT(from.m_offset != -1);
     {
         ASSERT(to.m_offset != -1);
         ASSERT(from.m_offset != -1);
-
-        uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(m_formatter.data()) + from.m_offset);
-        intptr_t relative = to.m_offset - from.m_offset;
-
-        linkWithOffset(location, relative);
+        m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset));
     }
 
     static void linkJump(void* code, JmpSrc from, void* to)
     }
 
     static void linkJump(void* code, JmpSrc from, void* to)
@@ -1515,9 +1544,7 @@ public:
         ASSERT(from.m_offset != -1);
         
         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
         ASSERT(from.m_offset != -1);
         
         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
-        intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(location);
-
-        linkWithOffset(location, relative);
+        linkJumpAbsolute(location, to);
     }
 
     // bah, this mathod should really be static, since it is used by the LinkBuffer.
     }
 
     // bah, this mathod should really be static, since it is used by the LinkBuffer.
@@ -1541,10 +1568,9 @@ public:
         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
         ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
 
         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
         ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
 
-        intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
-        linkWithOffset(reinterpret_cast<uint16_t*>(from), relative);
+        linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
 
 
-        ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 2, 2 * sizeof(uint16_t));
+        ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
     }
     
     static void relinkCall(void* from, void* to)
     }
     
     static void relinkCall(void* from, void* to)
@@ -1613,14 +1639,14 @@ private:
     static void setInt32(void* code, uint32_t value)
     {
         uint16_t* location = reinterpret_cast<uint16_t*>(code);
     static void setInt32(void* code, uint32_t value)
     {
         uint16_t* location = reinterpret_cast<uint16_t*>(code);
+        ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
 
 
-        uint16_t lo16 = value;
-        uint16_t hi16 = value >> 16;
-
-        spliceHi5(location - 4, lo16);
-        spliceLo11(location - 3, lo16);
-        spliceHi5(location - 2, hi16);
-        spliceLo11(location - 1, hi16);
+        ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value));
+        ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16));
+        location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
+        location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16);
+        location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
+        location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
 
         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
     }
 
         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
     }
@@ -1630,41 +1656,89 @@ private:
         setInt32(code, reinterpret_cast<uint32_t>(value));
     }
 
         setInt32(code, reinterpret_cast<uint32_t>(value));
     }
 
-    // Linking & patching:
-    // This method assumes that the JmpSrc being linked is a T4 b instruction.
-    static void linkWithOffset(uint16_t* instruction, intptr_t relative)
-    {
-        // Currently branches > 16m = mostly deathy.
-        if (((relative << 7) >> 7) != relative) {
-            // FIXME: This CRASH means we cannot turn the JIT on by default on arm-v7.
-            fprintf(stderr, "Error: Cannot link T4b.\n");
-            CRASH();
-        }
-        
-        // ARM encoding for the top two bits below the sign bit is 'peculiar'.
-        if (relative >= 0)
-            relative ^= 0xC00000;
+    static bool isB(void* address)
+    {
+        uint16_t* instruction = static_cast<uint16_t*>(address);
+        return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b);
+    }
 
 
-        // All branch offsets should be an even distance.
-        ASSERT(!(relative & 1));
+    static bool isBX(void* address)
+    {
+        uint16_t* instruction = static_cast<uint16_t*>(address);
+        return (instruction[0] & 0xff87) == OP_BX;
+    }
 
 
-        int word1 = ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
-        int word2 = ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
+    static bool isMOV_imm_T3(void* address)
+    {
+        uint16_t* instruction = static_cast<uint16_t*>(address);
+        return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0);
+    }
 
 
-        instruction[-2] = OP_B_T4a | word1;
-        instruction[-1] = OP_B_T4b | word2;
+    static bool isMOVT(void* address)
+    {
+        uint16_t* instruction = static_cast<uint16_t*>(address);
+        return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0);
     }
 
     }
 
-    // These functions can be used to splice 16-bit immediates back into previously generated instructions.
-    static void spliceHi5(uint16_t* where, uint16_t what)
+    static bool isNOP_T1(void* address)
     {
     {
-        uint16_t pattern = (what >> 12) | ((what & 0x0800) >> 1);
-        *where = (*where & 0xFBF0) | pattern;
+        uint16_t* instruction = static_cast<uint16_t*>(address);
+        return instruction[0] == OP_NOP_T1;
     }
     }
-    static void spliceLo11(uint16_t* where, uint16_t what)
+
+    static bool isNOP_T2(void* address)
     {
     {
-        uint16_t pattern = ((what & 0x0700) << 4) | (what & 0x00FF);
-        *where = (*where & 0x8F00) | pattern;
+        uint16_t* instruction = static_cast<uint16_t*>(address);
+        return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b);
+    }
+
+    static void linkJumpAbsolute(uint16_t* instruction, void* target)
+    {
+        // FIMXE: this should be up in the MacroAssembler layer. :-(
+        const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
+
+        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
+        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
+
+        ASSERT( (isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
+            || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) );
+
+        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
+        if (((relative << 7) >> 7) == relative) {
+            // ARM encoding for the top two bits below the sign bit is 'peculiar'.
+            if (relative >= 0)
+                relative ^= 0xC00000;
+
+            // All branch offsets should be an even distance.
+            ASSERT(!(relative & 1));
+            // There may be a better way to fix this, but right now put the NOPs first, since in the
+            // case of an conditional branch this will be coming after an ITTT predicating *three*
+            // instructions!  Looking backwards to modify the ITTT to an IT is not easy, due to
+            // variable wdith encoding - the previous instruction might *look* like an ITTT but
+            // actually be the second half of a 2-word op.
+            instruction[-5] = OP_NOP_T1;
+            instruction[-4] = OP_NOP_T2a;
+            instruction[-3] = OP_NOP_T2b;
+            instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
+            instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
+        } else {
+            ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
+            ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
+            instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
+            instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
+            instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
+            instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
+            instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
+        }
+    }
+
+    static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
+    {
+        return op | (imm.m_value.i << 10) | imm.m_value.imm4;
+    }
+    static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
+    {
+        return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
     }
 
     class ARMInstructionFormatter {
     }
 
     class ARMInstructionFormatter {
@@ -1723,8 +1797,11 @@ private:
 
         void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
         {
 
         void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
         {
-            m_buffer.putShort(op | (imm.m_value.i << 10) | imm4);
-            m_buffer.putShort((imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8);
+            ARMThumbImmediate newImm = imm;
+            newImm.m_value.imm4 = imm4;
+
+            m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm));
+            m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
         }
 
         void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
         }
 
         void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
@@ -1749,10 +1826,12 @@ private:
     private:
         AssemblerBuffer m_buffer;
     } m_formatter;
     private:
         AssemblerBuffer m_buffer;
     } m_formatter;
+
+    Vector<LinkRecord> m_jumpsToLink;
 };
 
 } // namespace JSC
 
 };
 
 } // namespace JSC
 
-#endif // ENABLE(ASSEMBLER) && PLATFORM_ARM_ARCH(7)
+#endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
 
 #endif // ARMAssembler_h
 
 #endif // ARMAssembler_h
index 0b23d02e8ba582ca5806347133a0c0d8de702baa..198e8d10adffa84fc078811d7ebf177df68192ad 100644 (file)
@@ -173,16 +173,16 @@ public:
     struct Imm32 {
         explicit Imm32(int32_t value)
             : m_value(value)
     struct Imm32 {
         explicit Imm32(int32_t value)
             : m_value(value)
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM)
             , m_isPointer(false)
 #endif
         {
         }
 
             , m_isPointer(false)
 #endif
         {
         }
 
-#if !PLATFORM(X86_64)
+#if !CPU(X86_64)
         explicit Imm32(ImmPtr ptr)
             : m_value(ptr.asIntptr())
         explicit Imm32(ImmPtr ptr)
             : m_value(ptr.asIntptr())
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM)
             , m_isPointer(true)
 #endif
         {
             , m_isPointer(true)
 #endif
         {
@@ -190,7 +190,7 @@ public:
 #endif
 
         int32_t m_value;
 #endif
 
         int32_t m_value;
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM)
         // We rely on being able to regenerate code to recover exception handling
         // information.  Since ARMv7 supports 16-bit immediates there is a danger
         // that if pointer values change the layout of the generated code will change.
         // We rely on being able to regenerate code to recover exception handling
         // information.  Since ARMv7 supports 16-bit immediates there is a danger
         // that if pointer values change the layout of the generated code will change.
@@ -321,7 +321,6 @@ public:
         }
 
         JmpSrc m_jmp;
         }
 
         JmpSrc m_jmp;
-
     private:
         Flags m_flags;
     };
     private:
         Flags m_flags;
     };
index f15b7f33498065c84b64b93c914c1658ad85ac24..af3c3be07ec00314e39d8c42f0344a9a09583884 100644 (file)
@@ -34,6 +34,8 @@
 #include "AssemblerBuffer.h"
 #include <wtf/SegmentedVector.h>
 
 #include "AssemblerBuffer.h"
 #include <wtf/SegmentedVector.h>
 
+#define ASSEMBLER_HAS_CONSTANT_POOL 1
+
 namespace JSC {
 
 /*
 namespace JSC {
 
 /*
@@ -84,7 +86,7 @@ namespace JSC {
 
 template <int maxPoolSize, int barrierSize, int maxInstructionSize, class AssemblerType>
 class AssemblerBufferWithConstantPool: public AssemblerBuffer {
 
 template <int maxPoolSize, int barrierSize, int maxInstructionSize, class AssemblerType>
 class AssemblerBufferWithConstantPool: public AssemblerBuffer {
-    typedef WTF::SegmentedVector<uint32_t, 512> LoadOffsets;
+    typedef SegmentedVector<uint32_t, 512> LoadOffsets;
 public:
     enum {
         UniqueConst,
 public:
     enum {
         UniqueConst,
@@ -177,6 +179,11 @@ public:
         return AssemblerBuffer::size();
     }
 
         return AssemblerBuffer::size();
     }
 
+    int uncheckedSize()
+    {
+        return AssemblerBuffer::size();
+    }
+
     void* executableCopy(ExecutablePool* allocator)
     {
         flushConstantPool(false);
     void* executableCopy(ExecutablePool* allocator)
     {
         flushConstantPool(false);
@@ -207,10 +214,10 @@ public:
     }
 
     // This flushing mechanism can be called after any unconditional jumps.
     }
 
     // This flushing mechanism can be called after any unconditional jumps.
-    void flushWithoutBarrier()
+    void flushWithoutBarrier(bool isForced = false)
     {
         // Flush if constant pool is more than 60% full to avoid overuse of this function.
     {
         // Flush if constant pool is more than 60% full to avoid overuse of this function.
-        if (5 * m_numConsts > 3 * maxPoolSize / sizeof(uint32_t))
+        if (isForced || 5 * m_numConsts > 3 * maxPoolSize / sizeof(uint32_t))
             flushConstantPool(false);
     }
 
             flushConstantPool(false);
     }
 
@@ -219,6 +226,11 @@ public:
         return m_pool;
     }
 
         return m_pool;
     }
 
+    int sizeOfConstantPool()
+    {
+        return m_numConsts;
+    }
+
 private:
     void correctDeltas(int insnSize)
     {
 private:
     void correctDeltas(int insnSize)
     {
@@ -276,7 +288,8 @@ private:
     {
         if (m_numConsts == 0)
             return;
     {
         if (m_numConsts == 0)
             return;
-        if ((m_maxDistance < nextInsnSize + m_lastConstDelta + barrierSize + (int)sizeof(uint32_t)))
+        int lastConstDelta = m_lastConstDelta > nextInsnSize ? m_lastConstDelta - nextInsnSize : 0;
+        if ((m_maxDistance < nextInsnSize + lastConstDelta + barrierSize + (int)sizeof(uint32_t)))
             flushConstantPool();
     }
 
             flushConstantPool();
     }
 
@@ -284,8 +297,8 @@ private:
     {
         if (m_numConsts == 0)
             return;
     {
         if (m_numConsts == 0)
             return;
-        if ((m_maxDistance < nextInsnSize + m_lastConstDelta + barrierSize + (int)sizeof(uint32_t)) ||
-            (m_numConsts + nextConstSize / sizeof(uint32_t) >= maxPoolSize))
+        if ((m_maxDistance < nextInsnSize + m_lastConstDelta + nextConstSize + barrierSize + (int)sizeof(uint32_t)) ||
+            (m_numConsts * sizeof(uint32_t) + nextConstSize >= maxPoolSize))
             flushConstantPool();
     }
 
             flushConstantPool();
     }
 
index 43d27e7e1079243b9c39b981b6fbb2f6745c75c9..76bd2057014588dd11678a49638f3f2928d23912 100644 (file)
 
 #if ENABLE(ASSEMBLER)
 
 
 #if ENABLE(ASSEMBLER)
 
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM_THUMB2)
 #include "MacroAssemblerARMv7.h"
 namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; };
 
 #include "MacroAssemblerARMv7.h"
 namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; };
 
-#elif PLATFORM(X86)
+#elif CPU(ARM_TRADITIONAL)
+#include "MacroAssemblerARM.h"
+namespace JSC { typedef MacroAssemblerARM MacroAssemblerBase; };
+
+#elif CPU(X86)
 #include "MacroAssemblerX86.h"
 namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; };
 
 #include "MacroAssemblerX86.h"
 namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; };
 
-#elif PLATFORM(X86_64)
+#elif CPU(X86_64)
 #include "MacroAssemblerX86_64.h"
 namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; };
 
 #include "MacroAssemblerX86_64.h"
 namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; };
 
@@ -56,7 +60,7 @@ public:
     using MacroAssemblerBase::jump;
     using MacroAssemblerBase::branch32;
     using MacroAssemblerBase::branch16;
     using MacroAssemblerBase::jump;
     using MacroAssemblerBase::branch32;
     using MacroAssemblerBase::branch16;
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     using MacroAssemblerBase::branchPtr;
     using MacroAssemblerBase::branchTestPtr;
 #endif
     using MacroAssemblerBase::branchPtr;
     using MacroAssemblerBase::branchTestPtr;
 #endif
@@ -129,7 +133,8 @@ public:
 
     // Ptr methods
     // On 32-bit platforms (i.e. x86), these methods directly map onto their 32-bit equivalents.
 
     // Ptr methods
     // On 32-bit platforms (i.e. x86), these methods directly map onto their 32-bit equivalents.
-#if !PLATFORM(X86_64)
+    // FIXME: should this use a test for 32-bitness instead of this specific exception?
+#if !CPU(X86_64)
     void addPtr(RegisterID src, RegisterID dest)
     {
         add32(src, dest);
     void addPtr(RegisterID src, RegisterID dest)
     {
         add32(src, dest);
@@ -175,16 +180,6 @@ public:
         or32(imm, dest);
     }
 
         or32(imm, dest);
     }
 
-    void rshiftPtr(RegisterID shift_amount, RegisterID dest)
-    {
-        rshift32(shift_amount, dest);
-    }
-
-    void rshiftPtr(Imm32 imm, RegisterID dest)
-    {
-        rshift32(imm, dest);
-    }
-
     void subPtr(RegisterID src, RegisterID dest)
     {
         sub32(src, dest);
     void subPtr(RegisterID src, RegisterID dest)
     {
         sub32(src, dest);
diff --git a/assembler/MacroAssemblerARM.cpp b/assembler/MacroAssemblerARM.cpp
new file mode 100644 (file)
index 0000000..b5b20fa
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2009 University of Szeged
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
+
+#include "MacroAssemblerARM.h"
+
+#if OS(LINUX)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <elf.h>
+#include <asm/hwcap.h>
+#endif
+
+namespace JSC {
+
+static bool isVFPPresent()
+{
+#if OS(LINUX)
+    int fd = open("/proc/self/auxv", O_RDONLY);
+    if (fd > 0) {
+        Elf32_auxv_t aux;
+        while (read(fd, &aux, sizeof(Elf32_auxv_t))) {
+            if (aux.a_type == AT_HWCAP) {
+                close(fd);
+                return aux.a_un.a_val & HWCAP_VFP;
+            }
+        }
+        close(fd);
+    }
+#endif
+
+    return false;
+}
+
+const bool MacroAssemblerARM::s_isVFPPresent = isVFPPresent();
+
+#if CPU(ARMV5_OR_LOWER)
+/* On ARMv5 and below, natural alignment is required. */
+void MacroAssemblerARM::load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
+{
+    ARMWord op2;
+
+    ASSERT(address.scale >= 0 && address.scale <= 3);
+    op2 = m_assembler.lsl(address.index, static_cast<int>(address.scale));
+
+    if (address.offset >= 0 && address.offset + 0x2 <= 0xff) {
+        m_assembler.add_r(ARMRegisters::S0, address.base, op2);
+        m_assembler.ldrh_u(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(address.offset));
+        m_assembler.ldrh_u(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(address.offset + 0x2));
+    } else if (address.offset < 0 && address.offset >= -0xff) {
+        m_assembler.add_r(ARMRegisters::S0, address.base, op2);
+        m_assembler.ldrh_d(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset));
+        m_assembler.ldrh_d(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset - 0x2));
+    } else {
+        m_assembler.ldr_un_imm(ARMRegisters::S0, address.offset);
+        m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, op2);
+        m_assembler.ldrh_r(dest, address.base, ARMRegisters::S0);
+        m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::OP2_IMM | 0x2);
+        m_assembler.ldrh_r(ARMRegisters::S0, address.base, ARMRegisters::S0);
+    }
+    m_assembler.orr_r(dest, dest, m_assembler.lsl(ARMRegisters::S0, 16));
+}
+#endif
+
+}
+
+#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
diff --git a/assembler/MacroAssemblerARM.h b/assembler/MacroAssemblerARM.h
new file mode 100644 (file)
index 0000000..21b8de8
--- /dev/null
@@ -0,0 +1,933 @@
+/*
+ * Copyright (C) 2008 Apple Inc.
+ * Copyright (C) 2009 University of Szeged
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MacroAssemblerARM_h
+#define MacroAssemblerARM_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
+
+#include "ARMAssembler.h"
+#include "AbstractMacroAssembler.h"
+
+namespace JSC {
+
+class MacroAssemblerARM : public AbstractMacroAssembler<ARMAssembler> {
+    static const int DoubleConditionMask = 0x0f;
+    static const int DoubleConditionBitSpecial = 0x10;
+    COMPILE_ASSERT(!(DoubleConditionBitSpecial & DoubleConditionMask), DoubleConditionBitSpecial_should_not_interfere_with_ARMAssembler_Condition_codes);
+public:
+    enum Condition {
+        Equal = ARMAssembler::EQ,
+        NotEqual = ARMAssembler::NE,
+        Above = ARMAssembler::HI,
+        AboveOrEqual = ARMAssembler::CS,
+        Below = ARMAssembler::CC,
+        BelowOrEqual = ARMAssembler::LS,
+        GreaterThan = ARMAssembler::GT,
+        GreaterThanOrEqual = ARMAssembler::GE,
+        LessThan = ARMAssembler::LT,
+        LessThanOrEqual = ARMAssembler::LE,
+        Overflow = ARMAssembler::VS,
+        Signed = ARMAssembler::MI,
+        Zero = ARMAssembler::EQ,
+        NonZero = ARMAssembler::NE
+    };
+
+    enum DoubleCondition {
+        // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
+        DoubleEqual = ARMAssembler::EQ,
+        DoubleNotEqual = ARMAssembler::NE | DoubleConditionBitSpecial,
+        DoubleGreaterThan = ARMAssembler::GT,
+        DoubleGreaterThanOrEqual = ARMAssembler::GE,
+        DoubleLessThan = ARMAssembler::CC,
+        DoubleLessThanOrEqual = ARMAssembler::LS,
+        // If either operand is NaN, these conditions always evaluate to true.
+        DoubleEqualOrUnordered = ARMAssembler::EQ | DoubleConditionBitSpecial,
+        DoubleNotEqualOrUnordered = ARMAssembler::NE,
+        DoubleGreaterThanOrUnordered = ARMAssembler::HI,
+        DoubleGreaterThanOrEqualOrUnordered = ARMAssembler::CS,
+        DoubleLessThanOrUnordered = ARMAssembler::LT,
+        DoubleLessThanOrEqualOrUnordered = ARMAssembler::LE,
+    };
+
+    static const RegisterID stackPointerRegister = ARMRegisters::sp;
+    static const RegisterID linkRegister = ARMRegisters::lr;
+
+    static const Scale ScalePtr = TimesFour;
+
+    void add32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.adds_r(dest, dest, src);
+    }
+
+    void add32(Imm32 imm, Address address)
+    {
+        load32(address, ARMRegisters::S1);
+        add32(imm, ARMRegisters::S1);
+        store32(ARMRegisters::S1, address);
+    }
+
+    void add32(Imm32 imm, RegisterID dest)
+    {
+        m_assembler.adds_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+    }
+
+    void add32(Address src, RegisterID dest)
+    {
+        load32(src, ARMRegisters::S1);
+        add32(ARMRegisters::S1, dest);
+    }
+
+    void and32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.ands_r(dest, dest, src);
+    }
+
+    void and32(Imm32 imm, RegisterID dest)
+    {
+        ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true);
+        if (w & ARMAssembler::OP2_INV_IMM)
+            m_assembler.bics_r(dest, dest, w & ~ARMAssembler::OP2_INV_IMM);
+        else
+            m_assembler.ands_r(dest, dest, w);
+    }
+
+    void lshift32(RegisterID shift_amount, RegisterID dest)
+    {
+        ARMWord w = ARMAssembler::getOp2(0x1f);
+        ASSERT(w != ARMAssembler::INVALID_IMM);
+        m_assembler.and_r(ARMRegisters::S0, shift_amount, w);
+
+        m_assembler.movs_r(dest, m_assembler.lsl_r(dest, ARMRegisters::S0));
+    }
+
+    void lshift32(Imm32 imm, RegisterID dest)
+    {
+        m_assembler.movs_r(dest, m_assembler.lsl(dest, imm.m_value & 0x1f));
+    }
+
+    void mul32(RegisterID src, RegisterID dest)
+    {
+        if (src == dest) {
+            move(src, ARMRegisters::S0);
+            src = ARMRegisters::S0;
+        }
+        m_assembler.muls_r(dest, dest, src);
+    }
+
+    void mul32(Imm32 imm, RegisterID src, RegisterID dest)
+    {
+        move(imm, ARMRegisters::S0);
+        m_assembler.muls_r(dest, src, ARMRegisters::S0);
+    }
+
+    void neg32(RegisterID srcDest)
+    {
+        m_assembler.rsbs_r(srcDest, srcDest, ARMAssembler::getOp2(0));
+    }
+
+    void not32(RegisterID dest)
+    {
+        m_assembler.mvns_r(dest, dest);
+    }
+
+    void or32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.orrs_r(dest, dest, src);
+    }
+
+    void or32(Imm32 imm, RegisterID dest)
+    {
+        m_assembler.orrs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+    }
+
+    void rshift32(RegisterID shift_amount, RegisterID dest)
+    {
+        ARMWord w = ARMAssembler::getOp2(0x1f);
+        ASSERT(w != ARMAssembler::INVALID_IMM);
+        m_assembler.and_r(ARMRegisters::S0, shift_amount, w);
+
+        m_assembler.movs_r(dest, m_assembler.asr_r(dest, ARMRegisters::S0));
+    }
+
+    void rshift32(Imm32 imm, RegisterID dest)
+    {
+        m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f));
+    }
+
+    void sub32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.subs_r(dest, dest, src);
+    }
+
+    void sub32(Imm32 imm, RegisterID dest)
+    {
+        m_assembler.subs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+    }
+
+    void sub32(Imm32 imm, Address address)
+    {
+        load32(address, ARMRegisters::S1);
+        sub32(imm, ARMRegisters::S1);
+        store32(ARMRegisters::S1, address);
+    }
+
+    void sub32(Address src, RegisterID dest)
+    {
+        load32(src, ARMRegisters::S1);
+        sub32(ARMRegisters::S1, dest);
+    }
+
+    void xor32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.eors_r(dest, dest, src);
+    }
+
+    void xor32(Imm32 imm, RegisterID dest)
+    {
+        m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+    }
+
+    void load32(ImplicitAddress address, RegisterID dest)
+    {
+        m_assembler.dataTransfer32(true, dest, address.base, address.offset);
+    }
+
+    void load32(BaseIndex address, RegisterID dest)
+    {
+        m_assembler.baseIndexTransfer32(true, dest, address.base, address.index, static_cast<int>(address.scale), address.offset);
+    }
+
+#if CPU(ARMV5_OR_LOWER)
+    void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest);
+#else
+    void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
+    {
+        load32(address, dest);
+    }
+#endif
+
+    DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
+    {
+        DataLabel32 dataLabel(this);
+        m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
+        m_assembler.dtr_ur(true, dest, address.base, ARMRegisters::S0);
+        return dataLabel;
+    }
+
+    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
+    {
+        Label label(this);
+        load32(address, dest);
+        return label;
+    }
+
+    void load16(BaseIndex address, RegisterID dest)
+    {
+        m_assembler.add_r(ARMRegisters::S0, address.base, m_assembler.lsl(address.index, address.scale));
+        if (address.offset>=0)
+            m_assembler.ldrh_u(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(address.offset));
+        else
+            m_assembler.ldrh_d(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset));
+    }
+
+    DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
+    {
+        DataLabel32 dataLabel(this);
+        m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
+        m_assembler.dtr_ur(false, src, address.base, ARMRegisters::S0);
+        return dataLabel;
+    }
+
+    void store32(RegisterID src, ImplicitAddress address)
+    {
+        m_assembler.dataTransfer32(false, src, address.base, address.offset);
+    }
+
+    void store32(RegisterID src, BaseIndex address)
+    {
+        m_assembler.baseIndexTransfer32(false, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
+    }
+
+    void store32(Imm32 imm, ImplicitAddress address)
+    {
+        if (imm.m_isPointer)
+            m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value);
+        else
+            move(imm, ARMRegisters::S1);
+        store32(ARMRegisters::S1, address);
+    }
+
+    void store32(RegisterID src, void* address)
+    {
+        m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
+        m_assembler.dtr_u(false, src, ARMRegisters::S0, 0);
+    }
+
+    void store32(Imm32 imm, void* address)
+    {
+        m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
+        if (imm.m_isPointer)
+            m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value);
+        else
+            m_assembler.moveImm(imm.m_value, ARMRegisters::S1);
+        m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
+    }
+
+    void pop(RegisterID dest)
+    {
+        m_assembler.pop_r(dest);
+    }
+
+    void push(RegisterID src)
+    {
+        m_assembler.push_r(src);
+    }
+
+    void push(Address address)
+    {
+        load32(address, ARMRegisters::S1);
+        push(ARMRegisters::S1);
+    }
+
+    void push(Imm32 imm)
+    {
+        move(imm, ARMRegisters::S0);
+        push(ARMRegisters::S0);
+    }
+
+    void move(Imm32 imm, RegisterID dest)
+    {
+        if (imm.m_isPointer)
+            m_assembler.ldr_un_imm(dest, imm.m_value);
+        else
+            m_assembler.moveImm(imm.m_value, dest);
+    }
+
+    void move(RegisterID src, RegisterID dest)
+    {
+        m_assembler.mov_r(dest, src);
+    }
+
+    void move(ImmPtr imm, RegisterID dest)
+    {
+        move(Imm32(imm), dest);
+    }
+
+    void swap(RegisterID reg1, RegisterID reg2)
+    {
+        m_assembler.mov_r(ARMRegisters::S0, reg1);
+        m_assembler.mov_r(reg1, reg2);
+        m_assembler.mov_r(reg2, ARMRegisters::S0);
+    }
+
+    void signExtend32ToPtr(RegisterID src, RegisterID dest)
+    {
+        if (src != dest)
+            move(src, dest);
+    }
+
+    void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
+    {
+        if (src != dest)
+            move(src, dest);
+    }
+
+    Jump branch32(Condition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
+    {
+        m_assembler.cmp_r(left, right);
+        return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
+    }
+
+    Jump branch32(Condition cond, RegisterID left, Imm32 right, int useConstantPool = 0)
+    {
+        if (right.m_isPointer) {
+            m_assembler.ldr_un_imm(ARMRegisters::S0, right.m_value);
+            m_assembler.cmp_r(left, ARMRegisters::S0);
+        } else
+            m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
+        return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
+    }
+
+    Jump branch32(Condition cond, RegisterID left, Address right)
+    {
+        load32(right, ARMRegisters::S1);
+        return branch32(cond, left, ARMRegisters::S1);
+    }
+
+    Jump branch32(Condition cond, Address left, RegisterID right)
+    {
+        load32(left, ARMRegisters::S1);
+        return branch32(cond, ARMRegisters::S1, right);
+    }
+
+    Jump branch32(Condition cond, Address left, Imm32 right)
+    {
+        load32(left, ARMRegisters::S1);
+        return branch32(cond, ARMRegisters::S1, right);
+    }
+
+    Jump branch32(Condition cond, BaseIndex left, Imm32 right)
+    {
+        load32(left, ARMRegisters::S1);
+        return branch32(cond, ARMRegisters::S1, right);
+    }
+
+    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
+    {
+        load32WithUnalignedHalfWords(left, ARMRegisters::S1);
+        return branch32(cond, ARMRegisters::S1, right);
+    }
+
+    Jump branch16(Condition cond, BaseIndex left, RegisterID right)
+    {
+        UNUSED_PARAM(cond);
+        UNUSED_PARAM(left);
+        UNUSED_PARAM(right);
+        ASSERT_NOT_REACHED();
+        return jump();
+    }
+
+    Jump branch16(Condition cond, BaseIndex left, Imm32 right)
+    {
+        load16(left, ARMRegisters::S0);
+        move(right, ARMRegisters::S1);
+        m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S1);
+        return m_assembler.jmp(ARMCondition(cond));
+    }
+
+    Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
+    {
+        ASSERT((cond == Zero) || (cond == NonZero));
+        m_assembler.tst_r(reg, mask);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
+    Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+    {
+        ASSERT((cond == Zero) || (cond == NonZero));
+        ARMWord w = m_assembler.getImm(mask.m_value, ARMRegisters::S0, true);
+        if (w & ARMAssembler::OP2_INV_IMM)
+            m_assembler.bics_r(ARMRegisters::S0, reg, w & ~ARMAssembler::OP2_INV_IMM);
+        else
+            m_assembler.tst_r(reg, w);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
+    Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    {
+        load32(address, ARMRegisters::S1);
+        return branchTest32(cond, ARMRegisters::S1, mask);
+    }
+
+    Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+    {
+        load32(address, ARMRegisters::S1);
+        return branchTest32(cond, ARMRegisters::S1, mask);
+    }
+
+    Jump jump()
+    {
+        return Jump(m_assembler.jmp());
+    }
+
+    void jump(RegisterID target)
+    {
+        move(target, ARMRegisters::pc);
+    }
+
+    void jump(Address address)
+    {
+        load32(address, ARMRegisters::pc);
+    }
+
+    Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        add32(src, dest);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
+    Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        add32(imm, dest);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
+    void mull32(RegisterID src1, RegisterID src2, RegisterID dest)
+    {
+        if (src1 == dest) {
+            move(src1, ARMRegisters::S0);
+            src1 = ARMRegisters::S0;
+        }
+        m_assembler.mull_r(ARMRegisters::S1, dest, src2, src1);
+        m_assembler.cmp_r(ARMRegisters::S1, m_assembler.asr(dest, 31));
+    }
+
+    Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        if (cond == Overflow) {
+            mull32(src, dest, dest);
+            cond = NonZero;
+        }
+        else
+            mul32(src, dest);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
+    Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        if (cond == Overflow) {
+            move(imm, ARMRegisters::S0);
+            mull32(ARMRegisters::S0, src, dest);
+            cond = NonZero;
+        }
+        else
+            mul32(imm, src, dest);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
+    Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        sub32(src, dest);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
+    Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        sub32(imm, dest);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
+    Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
+        or32(src, dest);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
+    void breakpoint()
+    {
+        m_assembler.bkpt(0);
+    }
+
+    Call nearCall()
+    {
+        prepareCall();
+        return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::LinkableNear);
+    }
+
+    Call call(RegisterID target)
+    {
+        prepareCall();
+        move(ARMRegisters::pc, target);
+        JmpSrc jmpSrc;
+        return Call(jmpSrc, Call::None);
+    }
+
+    void call(Address address)
+    {
+        call32(address.base, address.offset);
+    }
+
+    void ret()
+    {
+        m_assembler.mov_r(ARMRegisters::pc, linkRegister);
+    }
+
+    void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+    {
+        m_assembler.cmp_r(left, right);
+        m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
+        m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
+    }
+
+    void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    {
+        m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
+        m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
+        m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
+    }
+
+    void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+    {
+        // ARM doesn't have byte registers
+        set32(cond, left, right, dest);
+    }
+
+    void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
+    {
+        // ARM doesn't have byte registers
+        load32(left, ARMRegisters::S1);
+        set32(cond, ARMRegisters::S1, right, dest);
+    }
+
+    void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    {
+        // ARM doesn't have byte registers
+        set32(cond, left, right, dest);
+    }
+
+    void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    {
+        load32(address, ARMRegisters::S1);
+        if (mask.m_value == -1)
+            m_assembler.cmp_r(0, ARMRegisters::S1);
+        else
+            m_assembler.tst_r(ARMRegisters::S1, m_assembler.getImm(mask.m_value, ARMRegisters::S0));
+        m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
+        m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
+    }
+
+    void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    {
+        // ARM doesn't have byte registers
+        setTest32(cond, address, mask, dest);
+    }
+
+    void add32(Imm32 imm, RegisterID src, RegisterID dest)
+    {
+        m_assembler.add_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+    }
+
+    void add32(Imm32 imm, AbsoluteAddress address)
+    {
+        m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
+        m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
+        add32(imm, ARMRegisters::S1);
+        m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr));
+        m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
+    }
+
+    void sub32(Imm32 imm, AbsoluteAddress address)
+    {
+        m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
+        m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
+        sub32(imm, ARMRegisters::S1);
+        m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr));
+        m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
+    }
+
+    void load32(void* address, RegisterID dest)
+    {
+        m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
+        m_assembler.dtr_u(true, dest, ARMRegisters::S0, 0);
+    }
+
+    Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
+    {
+        load32(left.m_ptr, ARMRegisters::S1);
+        return branch32(cond, ARMRegisters::S1, right);
+    }
+
+    Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
+    {
+        load32(left.m_ptr, ARMRegisters::S1);
+        return branch32(cond, ARMRegisters::S1, right);
+    }
+
+    Call call()
+    {
+        prepareCall();
+        return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::Linkable);
+    }
+
+    Call tailRecursiveCall()
+    {
+        return Call::fromTailJump(jump());
+    }
+
+    Call makeTailRecursiveCall(Jump oldJump)
+    {
+        return Call::fromTailJump(oldJump);
+    }
+
+    DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
+    {
+        DataLabelPtr dataLabel(this);
+        m_assembler.ldr_un_imm(dest, reinterpret_cast<ARMWord>(initialValue.m_value));
+        return dataLabel;
+    }
+
+    Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    {
+        dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S1);
+        Jump jump = branch32(cond, left, ARMRegisters::S1, true);
+        return jump;
+    }
+
+    Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    {
+        load32(left, ARMRegisters::S1);
+        dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S0);
+        Jump jump = branch32(cond, ARMRegisters::S0, ARMRegisters::S1, true);
+        return jump;
+    }
+
+    DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+    {
+        DataLabelPtr dataLabel = moveWithPatch(initialValue, ARMRegisters::S1);
+        store32(ARMRegisters::S1, address);
+        return dataLabel;
+    }
+
+    DataLabelPtr storePtrWithPatch(ImplicitAddress address)
+    {
+        return storePtrWithPatch(ImmPtr(0), address);
+    }
+
+    // Floating point operators
+    bool supportsFloatingPoint() const
+    {
+        return s_isVFPPresent;
+    }
+
+    bool supportsFloatingPointTruncate() const
+    {
+        return false;
+    }
+
+    void loadDouble(ImplicitAddress address, FPRegisterID dest)
+    {
+        m_assembler.doubleTransfer(true, dest, address.base, address.offset);
+    }
+
+    void loadDouble(void* address, FPRegisterID dest)
+    {
+        m_assembler.ldr_un_imm(ARMRegisters::S0, (ARMWord)address);
+        m_assembler.fdtr_u(true, dest, ARMRegisters::S0, 0);
+    }
+
+    void storeDouble(FPRegisterID src, ImplicitAddress address)
+    {
+        m_assembler.doubleTransfer(false, src, address.base, address.offset);
+    }
+
+    void addDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.faddd_r(dest, dest, src);
+    }
+
+    void addDouble(Address src, FPRegisterID dest)
+    {
+        loadDouble(src, ARMRegisters::SD0);
+        addDouble(ARMRegisters::SD0, dest);
+    }
+
+    void divDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.fdivd_r(dest, dest, src);
+    }
+
+    void divDouble(Address src, FPRegisterID dest)
+    {
+        ASSERT_NOT_REACHED(); // Untested
+        loadDouble(src, ARMRegisters::SD0);
+        divDouble(ARMRegisters::SD0, dest);
+    }
+
+    void subDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.fsubd_r(dest, dest, src);
+    }
+
+    void subDouble(Address src, FPRegisterID dest)
+    {
+        loadDouble(src, ARMRegisters::SD0);
+        subDouble(ARMRegisters::SD0, dest);
+    }
+
+    void mulDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.fmuld_r(dest, dest, src);
+    }
+
+    void mulDouble(Address src, FPRegisterID dest)
+    {
+        loadDouble(src, ARMRegisters::SD0);
+        mulDouble(ARMRegisters::SD0, dest);
+    }
+
+    void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
+    {
+        m_assembler.fmsr_r(dest, src);
+        m_assembler.fsitod_r(dest, dest);
+    }
+
+    void convertInt32ToDouble(Address src, FPRegisterID dest)
+    {
+        ASSERT_NOT_REACHED(); // Untested
+        // flds does not worth the effort here
+        load32(src, ARMRegisters::S1);
+        convertInt32ToDouble(ARMRegisters::S1, dest);
+    }
+
+    void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
+    {
+        ASSERT_NOT_REACHED(); // Untested
+        // flds does not worth the effort here
+        m_assembler.ldr_un_imm(ARMRegisters::S1, (ARMWord)src.m_ptr);
+        m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
+        convertInt32ToDouble(ARMRegisters::S1, dest);
+    }
+
+    Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
+    {
+        m_assembler.fcmpd_r(left, right);
+        m_assembler.fmstat();
+        if (cond & DoubleConditionBitSpecial)
+            m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::VS);
+        return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond & ~DoubleConditionMask)));
+    }
+
+    // Truncates 'src' to an integer, and places the resulting 'dest'.
+    // If the result is not representable as a 32 bit value, branch.
+    // May also branch for some values that are representable in 32 bits
+    // (specifically, in this case, INT_MIN).
+    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
+    {
+        UNUSED_PARAM(src);
+        UNUSED_PARAM(dest);
+        ASSERT_NOT_REACHED();
+        return jump();
+    }
+
+    // Convert 'src' to an integer, and places the resulting 'dest'.
+    // If the result is not representable as a 32 bit value, branch.
+    // May also branch for some values that are representable in 32 bits
+    // (specifically, in this case, 0).
+    void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
+    {
+        m_assembler.ftosid_r(ARMRegisters::SD0, src);
+        m_assembler.fmrs_r(dest, ARMRegisters::SD0);
+
+        // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
+        m_assembler.fsitod_r(ARMRegisters::SD0, ARMRegisters::SD0);
+        failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, ARMRegisters::SD0));
+
+        // If the result is zero, it might have been -0.0, and 0.0 equals to -0.0
+        failureCases.append(branchTest32(Zero, dest));
+    }
+
+    void zeroDouble(FPRegisterID srcDest)
+    {
+        m_assembler.mov_r(ARMRegisters::S0, ARMAssembler::getOp2(0));
+        convertInt32ToDouble(ARMRegisters::S0, srcDest);
+    }
+
+protected:
+    ARMAssembler::Condition ARMCondition(Condition cond)
+    {
+        return static_cast<ARMAssembler::Condition>(cond);
+    }
+
+    void ensureSpace(int insnSpace, int constSpace)
+    {
+        m_assembler.ensureSpace(insnSpace, constSpace);
+    }
+
+    int sizeOfConstantPool()
+    {
+        return m_assembler.sizeOfConstantPool();
+    }
+
+    void prepareCall()
+    {
+        ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
+
+        m_assembler.mov_r(linkRegister, ARMRegisters::pc);
+    }
+
+    void call32(RegisterID base, int32_t offset)
+    {
+        if (base == ARMRegisters::sp)
+            offset += 4;
+
+        if (offset >= 0) {
+            if (offset <= 0xfff) {
+                prepareCall();
+                m_assembler.dtr_u(true, ARMRegisters::pc, base, offset);
+            } else if (offset <= 0xfffff) {
+                m_assembler.add_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
+                prepareCall();
+                m_assembler.dtr_u(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff);
+            } else {
+                ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
+                prepareCall();
+                m_assembler.dtr_ur(true, ARMRegisters::pc, base, reg);
+            }
+        } else  {
+            offset = -offset;
+            if (offset <= 0xfff) {
+                prepareCall();
+                m_assembler.dtr_d(true, ARMRegisters::pc, base, offset);
+            } else if (offset <= 0xfffff) {
+                m_assembler.sub_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
+                prepareCall();
+                m_assembler.dtr_d(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff);
+            } else {
+                ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
+                prepareCall();
+                m_assembler.dtr_dr(true, ARMRegisters::pc, base, reg);
+            }
+        }
+    }
+
+private:
+    friend class LinkBuffer;
+    friend class RepatchBuffer;
+
+    static void linkCall(void* code, Call call, FunctionPtr function)
+    {
+        ARMAssembler::linkCall(code, call.m_jmp, function.value());
+    }
+
+    static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
+    {
+        ARMAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
+    }
+
+    static void repatchCall(CodeLocationCall call, FunctionPtr destination)
+    {
+        ARMAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
+    }
+
+    static const bool s_isVFPPresent;
+};
+
+}
+
+#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
+
+#endif // MacroAssemblerARM_h
index f7a84027f75dff8f81653054830c334002422de9..532a9cfd2883a4e6d6e01a6a6aad264f45bcb22d 100644 (file)
@@ -39,9 +39,9 @@ class MacroAssemblerARMv7 : public AbstractMacroAssembler<ARMv7Assembler> {
     // FIXME: switch dataTempRegister & addressTempRegister, or possibly use r7?
     //        - dTR is likely used more than aTR, and we'll get better instruction
     //        encoding if it's in the low 8 registers.
     // FIXME: switch dataTempRegister & addressTempRegister, or possibly use r7?
     //        - dTR is likely used more than aTR, and we'll get better instruction
     //        encoding if it's in the low 8 registers.
-    static const ARM::RegisterID dataTempRegister = ARM::ip;
-    static const RegisterID addressTempRegister = ARM::r3;
-    static const FPRegisterID fpTempRegister = ARM::d7;
+    static const ARMRegisters::RegisterID dataTempRegister = ARMRegisters::ip;
+    static const RegisterID addressTempRegister = ARMRegisters::r3;
+    static const FPRegisterID fpTempRegister = ARMRegisters::d7;
 
     struct ArmAddress {
         enum AddressType {
 
     struct ArmAddress {
         enum AddressType {
@@ -93,17 +93,25 @@ public:
         Zero = ARMv7Assembler::ConditionEQ,
         NonZero = ARMv7Assembler::ConditionNE
     };
         Zero = ARMv7Assembler::ConditionEQ,
         NonZero = ARMv7Assembler::ConditionNE
     };
-
     enum DoubleCondition {
     enum DoubleCondition {
+        // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
         DoubleEqual = ARMv7Assembler::ConditionEQ,
         DoubleEqual = ARMv7Assembler::ConditionEQ,
+        DoubleNotEqual = ARMv7Assembler::ConditionVC, // Not the right flag! check for this & handle differently.
         DoubleGreaterThan = ARMv7Assembler::ConditionGT,
         DoubleGreaterThanOrEqual = ARMv7Assembler::ConditionGE,
         DoubleLessThan = ARMv7Assembler::ConditionLO,
         DoubleLessThanOrEqual = ARMv7Assembler::ConditionLS,
         DoubleGreaterThan = ARMv7Assembler::ConditionGT,
         DoubleGreaterThanOrEqual = ARMv7Assembler::ConditionGE,
         DoubleLessThan = ARMv7Assembler::ConditionLO,
         DoubleLessThanOrEqual = ARMv7Assembler::ConditionLS,
+        // If either operand is NaN, these conditions always evaluate to true.
+        DoubleEqualOrUnordered = ARMv7Assembler::ConditionVS, // Not the right flag! check for this & handle differently.
+        DoubleNotEqualOrUnordered = ARMv7Assembler::ConditionNE,
+        DoubleGreaterThanOrUnordered = ARMv7Assembler::ConditionHI,
+        DoubleGreaterThanOrEqualOrUnordered = ARMv7Assembler::ConditionHS,
+        DoubleLessThanOrUnordered = ARMv7Assembler::ConditionLT,
+        DoubleLessThanOrEqualOrUnordered = ARMv7Assembler::ConditionLE,
     };
 
     };
 
-    static const RegisterID stackPointerRegister = ARM::sp;
-    static const RegisterID linkRegister = ARM::lr;
+    static const RegisterID stackPointerRegister = ARMRegisters::sp;
+    static const RegisterID linkRegister = ARMRegisters::lr;
 
     // Integer arithmetic operations:
     //
 
     // Integer arithmetic operations:
     //
@@ -189,14 +197,19 @@ public:
         }
     }
 
         }
     }
 
-    void lshift32(Imm32 imm, RegisterID dest)
+    void lshift32(RegisterID shift_amount, RegisterID dest)
     {
     {
-        m_assembler.lsl(dest, dest, imm.m_value);
+        // Clamp the shift to the range 0..31
+        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
+        ASSERT(armImm.isValid());
+        m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
+
+        m_assembler.lsl(dest, dest, dataTempRegister);
     }
 
     }
 
-    void lshift32(RegisterID shift_amount, RegisterID dest)
+    void lshift32(Imm32 imm, RegisterID dest)
     {
     {
-        m_assembler.lsl(dest, dest, shift_amount);
+        m_assembler.lsl(dest, dest, imm.m_value & 0x1f);
     }
 
     void mul32(RegisterID src, RegisterID dest)
     }
 
     void mul32(RegisterID src, RegisterID dest)
@@ -233,12 +246,17 @@ public:
 
     void rshift32(RegisterID shift_amount, RegisterID dest)
     {
 
     void rshift32(RegisterID shift_amount, RegisterID dest)
     {
-        m_assembler.asr(dest, dest, shift_amount);
+        // Clamp the shift to the range 0..31
+        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
+        ASSERT(armImm.isValid());
+        m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
+
+        m_assembler.asr(dest, dest, dataTempRegister);
     }
 
     void rshift32(Imm32 imm, RegisterID dest)
     {
     }
 
     void rshift32(Imm32 imm, RegisterID dest)
     {
-        m_assembler.asr(dest, dest, imm.m_value);
+        m_assembler.asr(dest, dest, imm.m_value & 0x1f);
     }
 
     void sub32(RegisterID src, RegisterID dest)
     }
 
     void sub32(RegisterID src, RegisterID dest)
@@ -375,6 +393,11 @@ public:
         load32(setupArmAddress(address), dest);
     }
 
         load32(setupArmAddress(address), dest);
     }
 
+    void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
+    {
+        load32(setupArmAddress(address), dest);
+    }
+
     void load32(void* address, RegisterID dest)
     {
         move(ImmPtr(address), addressTempRegister);
     void load32(void* address, RegisterID dest)
     {
         move(ImmPtr(address), addressTempRegister);
@@ -526,12 +549,30 @@ public:
     {
         m_assembler.vcmp_F64(left, right);
         m_assembler.vmrs_APSR_nzcv_FPSCR();
     {
         m_assembler.vcmp_F64(left, right);
         m_assembler.vmrs_APSR_nzcv_FPSCR();
+
+        if (cond == DoubleNotEqual) {
+            // ConditionNE jumps if NotEqual *or* unordered - force the unordered cases not to jump.
+            Jump unordered = makeBranch(ARMv7Assembler::ConditionVS);
+            Jump result = makeBranch(ARMv7Assembler::ConditionNE);
+            unordered.link(this);
+            return result;
+        }
+        if (cond == DoubleEqualOrUnordered) {
+            Jump unordered = makeBranch(ARMv7Assembler::ConditionVS);
+            Jump notEqual = makeBranch(ARMv7Assembler::ConditionNE);
+            unordered.link(this);
+            // We get here if either unordered, or equal.
+            Jump result = makeJump();
+            notEqual.link(this);
+            return result;
+        }
         return makeBranch(cond);
     }
 
     Jump branchTruncateDoubleToInt32(FPRegisterID, RegisterID)
     {
         ASSERT_NOT_REACHED();
         return makeBranch(cond);
     }
 
     Jump branchTruncateDoubleToInt32(FPRegisterID, RegisterID)
     {
         ASSERT_NOT_REACHED();
+        return jump();
     }
 
 
     }
 
 
@@ -546,13 +587,13 @@ public:
     void pop(RegisterID dest)
     {
         // store postindexed with writeback
     void pop(RegisterID dest)
     {
         // store postindexed with writeback
-        m_assembler.ldr(dest, ARM::sp, sizeof(void*), false, true);
+        m_assembler.ldr(dest, ARMRegisters::sp, sizeof(void*), false, true);
     }
 
     void push(RegisterID src)
     {
         // store preindexed with writeback
     }
 
     void push(RegisterID src)
     {
         // store preindexed with writeback
-        m_assembler.str(src, ARM::sp, -sizeof(void*), true, true);
+        m_assembler.str(src, ARMRegisters::sp, -sizeof(void*), true, true);
     }
 
     void push(Address address)
     }
 
     void push(Address address)
@@ -716,6 +757,13 @@ public:
         return branch32(cond, addressTempRegister, right);
     }
 
         return branch32(cond, addressTempRegister, right);
     }
 
+    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
+    {
+        // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
+        load32WithUnalignedHalfWords(left, addressTempRegister);
+        return branch32(cond, addressTempRegister, right);
+    }
+
     Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
     {
         load32(left.m_ptr, dataTempRegister);
     Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
     {
         load32(left.m_ptr, dataTempRegister);
@@ -977,13 +1025,15 @@ public:
 protected:
     ARMv7Assembler::JmpSrc makeJump()
     {
 protected:
     ARMv7Assembler::JmpSrc makeJump()
     {
-        return m_assembler.b();
+        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
+        return m_assembler.bx(dataTempRegister);
     }
 
     ARMv7Assembler::JmpSrc makeBranch(ARMv7Assembler::Condition cond)
     {
     }
 
     ARMv7Assembler::JmpSrc makeBranch(ARMv7Assembler::Condition cond)
     {
-        m_assembler.it(cond);
-        return m_assembler.b();
+        m_assembler.it(cond, true, true);
+        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
+        return m_assembler.bx(dataTempRegister);
     }
     ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); }
     ARMv7Assembler::JmpSrc makeBranch(DoubleCondition cond) { return makeBranch(armV7Condition(cond)); }
     }
     ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); }
     ARMv7Assembler::JmpSrc makeBranch(DoubleCondition cond) { return makeBranch(armV7Condition(cond)); }
@@ -1038,7 +1088,7 @@ protected:
         return addressTempRegister;
     }
 
         return addressTempRegister;
     }
 
-    DataLabel32 moveFixedWidthEncoding(Imm32 imm, RegisterID dst)
+    void moveFixedWidthEncoding(Imm32 imm, RegisterID dst)
     {
         uint32_t value = imm.m_value;
         m_assembler.movT3(dst, ARMThumbImmediate::makeUInt16(value & 0xffff));
     {
         uint32_t value = imm.m_value;
         m_assembler.movT3(dst, ARMThumbImmediate::makeUInt16(value & 0xffff));
index 341a7ff338e51011c0dc8afd0ae1e96ef55ffc23..cae8bf68e25f26e591ceb2b7d69a55adca98176a 100644 (file)
@@ -37,7 +37,7 @@
 
 // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
 // instruction address on the platform (for example, check any alignment requirements).
 
 // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
 // instruction address on the platform (for example, check any alignment requirements).
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM_THUMB2)
 // ARM/thumb instructions must be 16-bit aligned, but all code pointers to be loaded
 // into the processor are decorated with the bottom bit set, indicating that this is
 // thumb code (as oposed to 32-bit traditional ARM).  The first test checks for both
 // ARM/thumb instructions must be 16-bit aligned, but all code pointers to be loaded
 // into the processor are decorated with the bottom bit set, indicating that this is
 // thumb code (as oposed to 32-bit traditional ARM).  The first test checks for both
@@ -69,7 +69,13 @@ public:
 
     template<typename FunctionType>
     explicit FunctionPtr(FunctionType* value)
 
     template<typename FunctionType>
     explicit FunctionPtr(FunctionType* value)
+#if COMPILER(RVCT)
+     // RVTC compiler needs C-style cast as it fails with the following error
+     // Error:  #694: reinterpret_cast cannot cast away const or other type qualifiers
+        : m_value((void*)(value))
+#else
         : m_value(reinterpret_cast<void*>(value))
         : m_value(reinterpret_cast<void*>(value))
+#endif
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
@@ -124,7 +130,7 @@ public:
     }
 
     explicit MacroAssemblerCodePtr(void* value)
     }
 
     explicit MacroAssemblerCodePtr(void* value)
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM_THUMB2)
         // Decorate the pointer as a thumb code pointer.
         : m_value(reinterpret_cast<char*>(value) + 1)
 #else
         // Decorate the pointer as a thumb code pointer.
         : m_value(reinterpret_cast<char*>(value) + 1)
 #else
@@ -141,7 +147,7 @@ public:
     }
 
     void* executableAddress() const { return m_value; }
     }
 
     void* executableAddress() const { return m_value; }
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM_THUMB2)
     // To use this pointer as a data address remove the decoration.
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return reinterpret_cast<char*>(m_value) - 1; }
 #else
     // To use this pointer as a data address remove the decoration.
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return reinterpret_cast<char*>(m_value) - 1; }
 #else
index 6e962406d1545e100e728810d82c400ac7a0129d..ca7c31a0796a4b65caf324647d898b5dfd5d520f 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <wtf/Platform.h>
 
 
 #include <wtf/Platform.h>
 
-#if ENABLE(ASSEMBLER) && PLATFORM(X86)
+#if ENABLE(ASSEMBLER) && CPU(X86)
 
 #include "MacroAssemblerX86Common.h"
 
 
 #include "MacroAssemblerX86Common.h"
 
index c9e3569e501842ab87d7c4ab4f176b6f5a5a6379..449df86c6673790f8a7f6e0b17a699c0ab646c9c 100644 (file)
 namespace JSC {
 
 class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
 namespace JSC {
 
 class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
+    static const int DoubleConditionBitInvert = 0x10;
+    static const int DoubleConditionBitSpecial = 0x20;
+    static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
+
 public:
 
     enum Condition {
 public:
 
     enum Condition {
@@ -56,15 +60,26 @@ public:
     };
 
     enum DoubleCondition {
     };
 
     enum DoubleCondition {
-        DoubleEqual = X86Assembler::ConditionE,
+        // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
+        DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial,
         DoubleNotEqual = X86Assembler::ConditionNE,
         DoubleGreaterThan = X86Assembler::ConditionA,
         DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
         DoubleNotEqual = X86Assembler::ConditionNE,
         DoubleGreaterThan = X86Assembler::ConditionA,
         DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
-        DoubleLessThan = X86Assembler::ConditionB,
-        DoubleLessThanOrEqual = X86Assembler::ConditionBE,
+        DoubleLessThan = X86Assembler::ConditionA | DoubleConditionBitInvert,
+        DoubleLessThanOrEqual = X86Assembler::ConditionAE | DoubleConditionBitInvert,
+        // If either operand is NaN, these conditions always evaluate to true.
+        DoubleEqualOrUnordered = X86Assembler::ConditionE,
+        DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial,
+        DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert,
+        DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert,
+        DoubleLessThanOrUnordered = X86Assembler::ConditionB,
+        DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE,
     };
     };
+    COMPILE_ASSERT(
+        !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
+        DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
 
 
-    static const RegisterID stackPointerRegister = X86::esp;
+    static const RegisterID stackPointerRegister = X86Registers::esp;
 
     // Integer arithmetic operations:
     //
 
     // Integer arithmetic operations:
     //
@@ -132,20 +147,20 @@ public:
     {
         // On x86 we can only shift by ecx; if asked to shift by another register we'll
         // need rejig the shift amount into ecx first, and restore the registers afterwards.
     {
         // On x86 we can only shift by ecx; if asked to shift by another register we'll
         // need rejig the shift amount into ecx first, and restore the registers afterwards.
-        if (shift_amount != X86::ecx) {
-            swap(shift_amount, X86::ecx);
+        if (shift_amount != X86Registers::ecx) {
+            swap(shift_amount, X86Registers::ecx);
 
             // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
             if (dest == shift_amount)
 
             // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
             if (dest == shift_amount)
-                m_assembler.shll_CLr(X86::ecx);
+                m_assembler.shll_CLr(X86Registers::ecx);
             // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
             // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
-            else if (dest == X86::ecx)
+            else if (dest == X86Registers::ecx)
                 m_assembler.shll_CLr(shift_amount);
             // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
             else
                 m_assembler.shll_CLr(dest);
         
                 m_assembler.shll_CLr(shift_amount);
             // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
             else
                 m_assembler.shll_CLr(dest);
         
-            swap(shift_amount, X86::ecx);
+            swap(shift_amount, X86Registers::ecx);
         } else
             m_assembler.shll_CLr(dest);
     }
         } else
             m_assembler.shll_CLr(dest);
     }
@@ -214,20 +229,20 @@ public:
     {
         // On x86 we can only shift by ecx; if asked to shift by another register we'll
         // need rejig the shift amount into ecx first, and restore the registers afterwards.
     {
         // On x86 we can only shift by ecx; if asked to shift by another register we'll
         // need rejig the shift amount into ecx first, and restore the registers afterwards.
-        if (shift_amount != X86::ecx) {
-            swap(shift_amount, X86::ecx);
+        if (shift_amount != X86Registers::ecx) {
+            swap(shift_amount, X86Registers::ecx);
 
             // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
             if (dest == shift_amount)
 
             // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
             if (dest == shift_amount)
-                m_assembler.sarl_CLr(X86::ecx);
+                m_assembler.sarl_CLr(X86Registers::ecx);
             // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
             // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
-            else if (dest == X86::ecx)
+            else if (dest == X86Registers::ecx)
                 m_assembler.sarl_CLr(shift_amount);
             // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
             else
                 m_assembler.sarl_CLr(dest);
         
                 m_assembler.sarl_CLr(shift_amount);
             // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
             else
                 m_assembler.sarl_CLr(dest);
         
-            swap(shift_amount, X86::ecx);
+            swap(shift_amount, X86Registers::ecx);
         } else
             m_assembler.sarl_CLr(dest);
     }
         } else
             m_assembler.sarl_CLr(dest);
     }
@@ -306,6 +321,11 @@ public:
         m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
     }
 
         m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
     }
 
+    void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
+    {
+        load32(address, dest);
+    }
+
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
         m_assembler.movl_mr_disp32(address.offset, address.base, dest);
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
         m_assembler.movl_mr_disp32(address.offset, address.base, dest);
@@ -411,20 +431,35 @@ public:
 
     void convertInt32ToDouble(Address src, FPRegisterID dest)
     {
 
     void convertInt32ToDouble(Address src, FPRegisterID dest)
     {
+        ASSERT(isSSE2Present());
         m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
     }
 
     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
     {
         ASSERT(isSSE2Present());
         m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
     }
 
     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
     {
         ASSERT(isSSE2Present());
-        m_assembler.ucomisd_rr(right, left);
-        return Jump(m_assembler.jCC(x86Condition(cond)));
-    }
 
 
-    Jump branchDouble(DoubleCondition cond, FPRegisterID left, Address right)
-    {
-        m_assembler.ucomisd_mr(right.offset, right.base, left);
-        return Jump(m_assembler.jCC(x86Condition(cond)));
+        if (cond & DoubleConditionBitInvert)
+            m_assembler.ucomisd_rr(left, right);
+        else
+            m_assembler.ucomisd_rr(right, left);
+
+        if (cond == DoubleEqual) {
+            Jump isUnordered(m_assembler.jp());
+            Jump result = Jump(m_assembler.je());
+            isUnordered.link(this);
+            return result;
+        } else if (cond == DoubleNotEqualOrUnordered) {
+            Jump isUnordered(m_assembler.jp());
+            Jump isEqual(m_assembler.je());
+            isUnordered.link(this);
+            Jump result = jump();
+            isEqual.link(this);
+            return result;
+        }
+
+        ASSERT(!(cond & DoubleConditionBitSpecial));
+        return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits)));
     }
 
     // Truncates 'src' to an integer, and places the resulting 'dest'.
     }
 
     // Truncates 'src' to an integer, and places the resulting 'dest'.
@@ -438,6 +473,25 @@ public:
         return branch32(Equal, dest, Imm32(0x80000000));
     }
 
         return branch32(Equal, dest, Imm32(0x80000000));
     }
 
+    // Convert 'src' to an integer, and places the resulting 'dest'.
+    // If the result is not representable as a 32 bit value, branch.
+    // May also branch for some values that are representable in 32 bits
+    // (specifically, in this case, 0).
+    void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.cvttsd2si_rr(src, dest);
+
+        // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
+        failureCases.append(branchTest32(Zero, dest));
+
+        // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
+        convertInt32ToDouble(dest, fpTemp);
+        m_assembler.ucomisd_rr(fpTemp, src);
+        failureCases.append(m_assembler.jp());
+        failureCases.append(m_assembler.jne());
+    }
+
     void zeroDouble(FPRegisterID srcDest)
     {
         ASSERT(isSSE2Present());
     void zeroDouble(FPRegisterID srcDest)
     {
         ASSERT(isSSE2Present());
@@ -488,7 +542,7 @@ public:
             m_assembler.movl_i32r(imm.m_value, dest);
     }
 
             m_assembler.movl_i32r(imm.m_value, dest);
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void move(RegisterID src, RegisterID dest)
     {
         // Note: on 64-bit this is is a full register move; perhaps it would be
     void move(RegisterID src, RegisterID dest)
     {
         // Note: on 64-bit this is is a full register move; perhaps it would be
@@ -499,15 +553,13 @@ public:
 
     void move(ImmPtr imm, RegisterID dest)
     {
 
     void move(ImmPtr imm, RegisterID dest)
     {
-        if (CAN_SIGN_EXTEND_U32_64(imm.asIntptr()))
-            m_assembler.movl_i32r(static_cast<int32_t>(imm.asIntptr()), dest);
-        else
-            m_assembler.movq_i64r(imm.asIntptr(), dest);
+        m_assembler.movq_i64r(imm.asIntptr(), dest);
     }
 
     void swap(RegisterID reg1, RegisterID reg2)
     {
     }
 
     void swap(RegisterID reg1, RegisterID reg2)
     {
-        m_assembler.xchgq_rr(reg1, reg2);
+        if (reg1 != reg2)
+            m_assembler.xchgq_rr(reg1, reg2);
     }
 
     void signExtend32ToPtr(RegisterID src, RegisterID dest)
     }
 
     void signExtend32ToPtr(RegisterID src, RegisterID dest)
@@ -607,6 +659,11 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
+    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
+    {
+        return branch32(cond, left, right);
+    }
+
     Jump branch16(Condition cond, BaseIndex left, RegisterID right)
     {
         m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
     Jump branch16(Condition cond, BaseIndex left, RegisterID right)
     {
         m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
@@ -882,18 +939,13 @@ protected:
         return static_cast<X86Assembler::Condition>(cond);
     }
 
         return static_cast<X86Assembler::Condition>(cond);
     }
 
-    X86Assembler::Condition x86Condition(DoubleCondition cond)
-    {
-        return static_cast<X86Assembler::Condition>(cond);
-    }
-
 private:
     // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
     // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
     friend class MacroAssemblerX86;
 
 private:
     // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
     // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
     friend class MacroAssemblerX86;
 
-#if PLATFORM(X86)
-#if PLATFORM(MAC)
+#if CPU(X86)
+#if OS(MAC_OS_X)
 
     // All X86 Macs are guaranteed to support at least SSE2,
     static bool isSSE2Present()
 
     // All X86 Macs are guaranteed to support at least SSE2,
     static bool isSSE2Present()
@@ -901,7 +953,7 @@ private:
         return true;
     }
 
         return true;
     }
 
-#else // PLATFORM(MAC)
+#else // OS(MAC_OS_X)
 
     enum SSE2CheckState {
         NotCheckedSSE2,
 
     enum SSE2CheckState {
         NotCheckedSSE2,
@@ -944,8 +996,8 @@ private:
     
     static SSE2CheckState s_sse2CheckState;
 
     
     static SSE2CheckState s_sse2CheckState;
 
-#endif // PLATFORM(MAC)
-#elif !defined(NDEBUG) // PLATFORM(X86)
+#endif // OS(MAC_OS_X)
+#elif !defined(NDEBUG) // CPU(X86)
 
     // On x86-64 we should never be checking for SSE2 in a non-debug build,
     // but non debug add this method to keep the asserts above happy.
 
     // On x86-64 we should never be checking for SSE2 in a non-debug build,
     // but non debug add this method to keep the asserts above happy.
index e3d296c14174b49613b06eff4783fef70efb5c59..ec93f8c657851e970d689819780e19a24836f53a 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <wtf/Platform.h>
 
 
 #include <wtf/Platform.h>
 
-#if ENABLE(ASSEMBLER) && PLATFORM(X86_64)
+#if ENABLE(ASSEMBLER) && CPU(X86_64)
 
 #include "MacroAssemblerX86Common.h"
 
 
 #include "MacroAssemblerX86Common.h"
 
@@ -38,7 +38,7 @@ namespace JSC {
 
 class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
 protected:
 
 class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
 protected:
-    static const X86::RegisterID scratchRegister = X86::r11;
+    static const X86Registers::RegisterID scratchRegister = X86Registers::r11;
 
 public:
     static const Scale ScalePtr = TimesEight;
 
 public:
     static const Scale ScalePtr = TimesEight;
@@ -79,12 +79,12 @@ public:
 
     void load32(void* address, RegisterID dest)
     {
 
     void load32(void* address, RegisterID dest)
     {
-        if (dest == X86::eax)
+        if (dest == X86Registers::eax)
             m_assembler.movl_mEAX(address);
         else {
             m_assembler.movl_mEAX(address);
         else {
-            move(X86::eax, dest);
+            move(X86Registers::eax, dest);
             m_assembler.movl_mEAX(address);
             m_assembler.movl_mEAX(address);
-            swap(X86::eax, dest);
+            swap(X86Registers::eax, dest);
         }
     }
 
         }
     }
 
@@ -102,10 +102,10 @@ public:
 
     void store32(Imm32 imm, void* address)
     {
 
     void store32(Imm32 imm, void* address)
     {
-        move(X86::eax, scratchRegister);
-        move(imm, X86::eax);
+        move(X86Registers::eax, scratchRegister);
+        move(imm, X86Registers::eax);
         m_assembler.movl_EAXm(address);
         m_assembler.movl_EAXm(address);
-        move(scratchRegister, X86::eax);
+        move(scratchRegister, X86Registers::eax);
     }
 
     Call call()
     }
 
     Call call()
@@ -192,33 +192,6 @@ public:
         m_assembler.orq_ir(imm.m_value, dest);
     }
 
         m_assembler.orq_ir(imm.m_value, dest);
     }
 
-    void rshiftPtr(RegisterID shift_amount, RegisterID dest)
-    {
-        // On x86 we can only shift by ecx; if asked to shift by another register we'll
-        // need rejig the shift amount into ecx first, and restore the registers afterwards.
-        if (shift_amount != X86::ecx) {
-            swap(shift_amount, X86::ecx);
-
-            // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
-            if (dest == shift_amount)
-                m_assembler.sarq_CLr(X86::ecx);
-            // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
-            else if (dest == X86::ecx)
-                m_assembler.sarq_CLr(shift_amount);
-            // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
-            else
-                m_assembler.sarq_CLr(dest);
-        
-            swap(shift_amount, X86::ecx);
-        } else
-            m_assembler.sarq_CLr(dest);
-    }
-
-    void rshiftPtr(Imm32 imm, RegisterID dest)
-    {
-        m_assembler.sarq_i8r(imm.m_value, dest);
-    }
-
     void subPtr(RegisterID src, RegisterID dest)
     {
         m_assembler.subq_rr(src, dest);
     void subPtr(RegisterID src, RegisterID dest)
     {
         m_assembler.subq_rr(src, dest);
@@ -258,12 +231,12 @@ public:
 
     void loadPtr(void* address, RegisterID dest)
     {
 
     void loadPtr(void* address, RegisterID dest)
     {
-        if (dest == X86::eax)
+        if (dest == X86Registers::eax)
             m_assembler.movq_mEAX(address);
         else {
             m_assembler.movq_mEAX(address);
         else {
-            move(X86::eax, dest);
+            move(X86Registers::eax, dest);
             m_assembler.movq_mEAX(address);
             m_assembler.movq_mEAX(address);
-            swap(X86::eax, dest);
+            swap(X86Registers::eax, dest);
         }
     }
 
         }
     }
 
@@ -285,24 +258,19 @@ public:
     
     void storePtr(RegisterID src, void* address)
     {
     
     void storePtr(RegisterID src, void* address)
     {
-        if (src == X86::eax)
+        if (src == X86Registers::eax)
             m_assembler.movq_EAXm(address);
         else {
             m_assembler.movq_EAXm(address);
         else {
-            swap(X86::eax, src);
+            swap(X86Registers::eax, src);
             m_assembler.movq_EAXm(address);
             m_assembler.movq_EAXm(address);
-            swap(X86::eax, src);
+            swap(X86Registers::eax, src);
         }
     }
 
     void storePtr(ImmPtr imm, ImplicitAddress address)
     {
         }
     }
 
     void storePtr(ImmPtr imm, ImplicitAddress address)
     {
-        intptr_t ptr = imm.asIntptr();
-        if (CAN_SIGN_EXTEND_32_64(ptr))
-            m_assembler.movq_i32m(static_cast<int>(ptr), address.offset, address.base);
-        else {
-            move(imm, scratchRegister);
-            storePtr(scratchRegister, address);
-        }
+        move(imm, scratchRegister);
+        storePtr(scratchRegister, address);
     }
 
     DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
     }
 
     DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
@@ -339,17 +307,8 @@ public:
 
     Jump branchPtr(Condition cond, RegisterID left, ImmPtr right)
     {
 
     Jump branchPtr(Condition cond, RegisterID left, ImmPtr right)
     {
-        intptr_t imm = right.asIntptr();
-        if (CAN_SIGN_EXTEND_32_64(imm)) {
-            if (!imm)
-                m_assembler.testq_rr(left, left);
-            else
-                m_assembler.cmpq_ir(imm, left);
-            return Jump(m_assembler.jCC(x86Condition(cond)));
-        } else {
-            move(right, scratchRegister);
-            return branchPtr(cond, left, scratchRegister);
-        }
+        move(right, scratchRegister);
+        return branchPtr(cond, left, scratchRegister);
     }
 
     Jump branchPtr(Condition cond, RegisterID left, Address right)
     }
 
     Jump branchPtr(Condition cond, RegisterID left, Address right)
index b5b8808b91afc0a377f5f324912f0b92e34eedbf..ab3d05f181d320511adcf5e5f9df2c0bc00b75b2 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <wtf/Platform.h>
 
 
 #include <wtf/Platform.h>
 
-#if ENABLE(ASSEMBLER) && (PLATFORM(X86) || PLATFORM(X86_64))
+#if ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64))
 
 #include "AssemblerBuffer.h"
 #include <stdint.h>
 
 #include "AssemblerBuffer.h"
 #include <stdint.h>
 namespace JSC {
 
 inline bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(signed char)value; }
 namespace JSC {
 
 inline bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(signed char)value; }
-#if PLATFORM(X86_64)
-inline bool CAN_SIGN_EXTEND_32_64(intptr_t value) { return value == (intptr_t)(int32_t)value; }
-inline bool CAN_SIGN_EXTEND_U32_64(intptr_t value) { return value == (intptr_t)(uint32_t)value; }
-#endif
 
 
-namespace X86 {
+namespace X86Registers {
     typedef enum {
         eax,
         ecx,
     typedef enum {
         eax,
         ecx,
@@ -54,7 +50,7 @@ namespace X86 {
         esi,
         edi,
 
         esi,
         edi,
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         r8,
         r9,
         r10,
         r8,
         r9,
         r10,
@@ -80,8 +76,8 @@ namespace X86 {
 
 class X86Assembler {
 public:
 
 class X86Assembler {
 public:
-    typedef X86::RegisterID RegisterID;
-    typedef X86::XMMRegisterID XMMRegisterID;
+    typedef X86Registers::RegisterID RegisterID;
+    typedef X86Registers::XMMRegisterID XMMRegisterID;
     typedef XMMRegisterID FPRegisterID;
 
     typedef enum {
     typedef XMMRegisterID FPRegisterID;
 
     typedef enum {
@@ -122,12 +118,12 @@ private:
         OP_XOR_GvEv                     = 0x33,
         OP_CMP_EvGv                     = 0x39,
         OP_CMP_GvEv                     = 0x3B,
         OP_XOR_GvEv                     = 0x33,
         OP_CMP_EvGv                     = 0x39,
         OP_CMP_GvEv                     = 0x3B,
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         PRE_REX                         = 0x40,
 #endif
         OP_PUSH_EAX                     = 0x50,
         OP_POP_EAX                      = 0x58,
         PRE_REX                         = 0x40,
 #endif
         OP_PUSH_EAX                     = 0x50,
         OP_POP_EAX                      = 0x58,
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         OP_MOVSXD_GvEv                  = 0x63,
 #endif
         PRE_OPERAND_SIZE                = 0x66,
         OP_MOVSXD_GvEv                  = 0x63,
 #endif
         PRE_OPERAND_SIZE                = 0x66,
@@ -300,7 +296,7 @@ public:
 
     // Arithmetic operations:
 
 
     // Arithmetic operations:
 
-#if !PLATFORM(X86_64)
+#if !CPU(X86_64)
     void adcl_im(int imm, void* addr)
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
     void adcl_im(int imm, void* addr)
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
@@ -350,7 +346,7 @@ public:
         }
     }
 
         }
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void addq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_ADD_EvGv, src, dst);
     void addq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_ADD_EvGv, src, dst);
@@ -427,7 +423,7 @@ public:
         }
     }
 
         }
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void andq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_AND_EvGv, src, dst);
     void andq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_AND_EvGv, src, dst);
@@ -513,7 +509,7 @@ public:
         }
     }
 
         }
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void orq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_OR_EvGv, src, dst);
     void orq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_OR_EvGv, src, dst);
@@ -579,7 +575,7 @@ public:
         }
     }
 
         }
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void subq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_SUB_EvGv, src, dst);
     void subq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_SUB_EvGv, src, dst);
@@ -645,7 +641,7 @@ public:
         }
     }
 
         }
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void xorq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst);
     void xorq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst);
@@ -693,7 +689,7 @@ public:
         m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
     }
 
         m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void sarq_CLr(RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
     void sarq_CLr(RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
@@ -793,7 +789,7 @@ public:
         m_formatter.immediate32(imm);
     }
 
         m_formatter.immediate32(imm);
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void cmpq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_CMP_EvGv, src, dst);
     void cmpq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_CMP_EvGv, src, dst);
@@ -901,7 +897,7 @@ public:
         m_formatter.immediate32(imm);
     }
 
         m_formatter.immediate32(imm);
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void testq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst);
     void testq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst);
@@ -975,7 +971,7 @@ public:
         m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
     }
 
         m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void xchgq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst);
     void xchgq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst);
@@ -1005,7 +1001,7 @@ public:
     void movl_mEAX(void* addr)
     {
         m_formatter.oneByteOp(OP_MOV_EAXOv);
     void movl_mEAX(void* addr)
     {
         m_formatter.oneByteOp(OP_MOV_EAXOv);
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
 #else
         m_formatter.immediate32(reinterpret_cast<int>(addr));
         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
 #else
         m_formatter.immediate32(reinterpret_cast<int>(addr));
@@ -1042,14 +1038,14 @@ public:
     void movl_EAXm(void* addr)
     {
         m_formatter.oneByteOp(OP_MOV_OvEAX);
     void movl_EAXm(void* addr)
     {
         m_formatter.oneByteOp(OP_MOV_OvEAX);
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
 #else
         m_formatter.immediate32(reinterpret_cast<int>(addr));
 #endif
     }
 
         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
 #else
         m_formatter.immediate32(reinterpret_cast<int>(addr));
 #endif
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void movq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_MOV_EvGv, src, dst);
     void movq_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_MOV_EvGv, src, dst);
@@ -1118,7 +1114,7 @@ public:
 #else
     void movl_rm(RegisterID src, void* addr)
     {
 #else
     void movl_rm(RegisterID src, void* addr)
     {
-        if (src == X86::eax)
+        if (src == X86Registers::eax)
             movl_EAXm(addr);
         else 
             m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
             movl_EAXm(addr);
         else 
             m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
@@ -1126,7 +1122,7 @@ public:
     
     void movl_mr(void* addr, RegisterID dst)
     {
     
     void movl_mr(void* addr, RegisterID dst)
     {
-        if (dst == X86::eax)
+        if (dst == X86Registers::eax)
             movl_mEAX(addr);
         else
             m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
             movl_mEAX(addr);
         else
             m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
@@ -1161,7 +1157,7 @@ public:
     {
         m_formatter.oneByteOp(OP_LEA, dst, base, offset);
     }
     {
         m_formatter.oneByteOp(OP_LEA, dst, base, offset);
     }
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void leaq_mr(int offset, RegisterID base, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_LEA, dst, base, offset);
     void leaq_mr(int offset, RegisterID base, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_LEA, dst, base, offset);
@@ -1327,7 +1323,7 @@ public:
         m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset);
     }
 
         m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset);
     }
 
-#if !PLATFORM(X86_64)
+#if !CPU(X86_64)
     void cvtsi2sd_mr(void* address, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
     void cvtsi2sd_mr(void* address, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
@@ -1347,7 +1343,7 @@ public:
         m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst);
     }
 
         m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst);
     }
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     void movq_rr(XMMRegisterID src, RegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_66);
     void movq_rr(XMMRegisterID src, RegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_66);
@@ -1373,7 +1369,7 @@ public:
         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
-#if !PLATFORM(X86_64)
+#if !CPU(X86_64)
     void movsd_mr(void* address, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
     void movsd_mr(void* address, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
@@ -1539,7 +1535,7 @@ public:
 
     static void repatchLoadPtrToLEA(void* where)
     {
 
     static void repatchLoadPtrToLEA(void* where)
     {
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         // On x86-64 pointer memory accesses require a 64-bit operand, and as such a REX prefix.
         // Skip over the prefix byte.
         where = reinterpret_cast<char*>(where) + 1;
         // On x86-64 pointer memory accesses require a 64-bit operand, and as such a REX prefix.
         // Skip over the prefix byte.
         where = reinterpret_cast<char*>(where) + 1;
@@ -1683,7 +1679,7 @@ private:
             memoryModRM(reg, base, index, scale, offset);
         }
 
             memoryModRM(reg, base, index, scale, offset);
         }
 
-#if !PLATFORM(X86_64)
+#if !CPU(X86_64)
         void oneByteOp(OneByteOpcodeID opcode, int reg, void* address)
         {
             m_buffer.ensureSpace(maxInstructionSize);
         void oneByteOp(OneByteOpcodeID opcode, int reg, void* address)
         {
             m_buffer.ensureSpace(maxInstructionSize);
@@ -1726,7 +1722,7 @@ private:
             memoryModRM(reg, base, index, scale, offset);
         }
 
             memoryModRM(reg, base, index, scale, offset);
         }
 
-#if !PLATFORM(X86_64)
+#if !CPU(X86_64)
         void twoByteOp(TwoByteOpcodeID opcode, int reg, void* address)
         {
             m_buffer.ensureSpace(maxInstructionSize);
         void twoByteOp(TwoByteOpcodeID opcode, int reg, void* address)
         {
             m_buffer.ensureSpace(maxInstructionSize);
@@ -1736,7 +1732,7 @@ private:
         }
 #endif
 
         }
 #endif
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         // Quad-word-sized operands:
         //
         // Used to format 64-bit operantions, planting a REX.w prefix.
         // Quad-word-sized operands:
         //
         // Used to format 64-bit operantions, planting a REX.w prefix.
@@ -1892,23 +1888,23 @@ private:
 
         // Internals; ModRm and REX formatters.
 
 
         // Internals; ModRm and REX formatters.
 
-        static const RegisterID noBase = X86::ebp;
-        static const RegisterID hasSib = X86::esp;
-        static const RegisterID noIndex = X86::esp;
-#if PLATFORM(X86_64)
-        static const RegisterID noBase2 = X86::r13;
-        static const RegisterID hasSib2 = X86::r12;
+        static const RegisterID noBase = X86Registers::ebp;
+        static const RegisterID hasSib = X86Registers::esp;
+        static const RegisterID noIndex = X86Registers::esp;
+#if CPU(X86_64)
+        static const RegisterID noBase2 = X86Registers::r13;
+        static const RegisterID hasSib2 = X86Registers::r12;
 
         // Registers r8 & above require a REX prefixe.
         inline bool regRequiresRex(int reg)
         {
 
         // Registers r8 & above require a REX prefixe.
         inline bool regRequiresRex(int reg)
         {
-            return (reg >= X86::r8);
+            return (reg >= X86Registers::r8);
         }
 
         // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed).
         inline bool byteRegRequiresRex(int reg)
         {
         }
 
         // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed).
         inline bool byteRegRequiresRex(int reg)
         {
-            return (reg >= X86::esp);
+            return (reg >= X86Registers::esp);
         }
 
         // Format a REX prefix byte.
         }
 
         // Format a REX prefix byte.
@@ -1971,7 +1967,7 @@ private:
         void memoryModRM(int reg, RegisterID base, int offset)
         {
             // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
         void memoryModRM(int reg, RegisterID base, int offset)
         {
             // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
             if ((base == hasSib) || (base == hasSib2)) {
 #else
             if (base == hasSib) {
             if ((base == hasSib) || (base == hasSib2)) {
 #else
             if (base == hasSib) {
@@ -1986,7 +1982,7 @@ private:
                     m_buffer.putIntUnchecked(offset);
                 }
             } else {
                     m_buffer.putIntUnchecked(offset);
                 }
             } else {
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
                 if (!offset && (base != noBase) && (base != noBase2))
 #else
                 if (!offset && (base != noBase))
                 if (!offset && (base != noBase) && (base != noBase2))
 #else
                 if (!offset && (base != noBase))
@@ -2005,7 +2001,7 @@ private:
         void memoryModRM_disp32(int reg, RegisterID base, int offset)
         {
             // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
         void memoryModRM_disp32(int reg, RegisterID base, int offset)
         {
             // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
             if ((base == hasSib) || (base == hasSib2)) {
 #else
             if (base == hasSib) {
             if ((base == hasSib) || (base == hasSib2)) {
 #else
             if (base == hasSib) {
@@ -2022,7 +2018,7 @@ private:
         {
             ASSERT(index != noIndex);
 
         {
             ASSERT(index != noIndex);
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
             if (!offset && (base != noBase) && (base != noBase2))
 #else
             if (!offset && (base != noBase))
             if (!offset && (base != noBase) && (base != noBase2))
 #else
             if (!offset && (base != noBase))
@@ -2037,7 +2033,7 @@ private:
             }
         }
 
             }
         }
 
-#if !PLATFORM(X86_64)
+#if !CPU(X86_64)
         void memoryModRM(int reg, void* address)
         {
             // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
         void memoryModRM(int reg, void* address)
         {
             // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
@@ -2052,6 +2048,6 @@ private:
 
 } // namespace JSC
 
 
 } // namespace JSC
 
-#endif // ENABLE(ASSEMBLER) && PLATFORM(X86)
+#endif // ENABLE(ASSEMBLER) && CPU(X86)
 
 #endif // X86Assembler_h
 
 #endif // X86Assembler_h
index 1f64992ea14580d403e0de8e333352cdc36b1f3c..fd56ece666c7788b1260aed3a2ab04eed264bd9b 100644 (file)
@@ -33,6 +33,8 @@
 #include "JIT.h"
 #include "JSValue.h"
 #include "Interpreter.h"
 #include "JIT.h"
 #include "JSValue.h"
 #include "Interpreter.h"
+#include "JSFunction.h"
+#include "JSStaticScopeObject.h"
 #include "Debugger.h"
 #include "BytecodeGenerator.h"
 #include <stdio.h>
 #include "Debugger.h"
 #include "BytecodeGenerator.h"
 #include <stdio.h>
@@ -49,7 +51,7 @@ static UString escapeQuotes(const UString& str)
     UString result = str;
     int pos = 0;
     while ((pos = result.find('\"', pos)) >= 0) {
     UString result = str;
     int pos = 0;
     while ((pos = result.find('\"', pos)) >= 0) {
-        result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1);
+        result = makeString(result.substr(0, pos), "\"\\\"\"", result.substr(pos + 1));
         pos += 4;
     }
     return result;
         pos += 4;
     }
     return result;
@@ -60,49 +62,50 @@ static UString valueToSourceString(ExecState* exec, JSValue val)
     if (!val)
         return "0";
 
     if (!val)
         return "0";
 
-    if (val.isString()) {
-        UString result("\"");
-        result += escapeQuotes(val.toString(exec)) + "\"";
-        return result;
-    } 
+    if (val.isString())
+        return makeString("\"", escapeQuotes(val.toString(exec)), "\"");
 
     return val.toString(exec);
 }
 
 
     return val.toString(exec);
 }
 
-static CString registerName(int r)
+static CString constantName(ExecState* exec, int k, JSValue value)
 {
 {
-    if (r == missingThisObjectMarker())
-        return "<null>";
-
-    return (UString("r") + UString::from(r)).UTF8String();
+    return makeString(valueToSourceString(exec, value), "(@k", UString::from(k - FirstConstantRegisterIndex), ")").UTF8String();
 }
 
 }
 
-static CString constantName(ExecState* exec, int k, JSValue value)
+static CString idName(int id0, const Identifier& ident)
 {
 {
-    return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String();
+    return makeString(ident.ustring(), "(@id", UString::from(id0), ")").UTF8String();
 }
 
 }
 
-static CString idName(int id0, const Identifier& ident)
+CString CodeBlock::registerName(ExecState* exec, int r) const
 {
 {
-    return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String();
+    if (r == missingThisObjectMarker())
+        return "<null>";
+
+    if (isConstantRegisterIndex(r))
+        return constantName(exec, r, getConstant(r));
+
+    return makeString("r", UString::from(r)).UTF8String();
 }
 
 static UString regexpToSourceString(RegExp* regExp)
 {
 }
 
 static UString regexpToSourceString(RegExp* regExp)
 {
-    UString pattern = UString("/") + regExp->pattern() + "/";
+    char postfix[5] = { '/', 0, 0, 0, 0 };
+    int index = 1;
     if (regExp->global())
     if (regExp->global())
-        pattern += "g";
+        postfix[index++] = 'g';
     if (regExp->ignoreCase())
     if (regExp->ignoreCase())
-        pattern += "i";
+        postfix[index++] = 'i';
     if (regExp->multiline())
     if (regExp->multiline())
-        pattern += "m";
+        postfix[index] = 'm';
 
 
-    return pattern;
+    return makeString("/", regExp->pattern(), postfix);
 }
 
 static CString regexpName(int re, RegExp* regexp)
 {
 }
 
 static CString regexpName(int re, RegExp* regexp)
 {
-    return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String();
+    return makeString(regexpToSourceString(regexp), "(@re", UString::from(re), ")").UTF8String();
 }
 
 static UString pointerToSourceString(void* p)
 }
 
 static UString pointerToSourceString(void* p)
@@ -133,49 +136,44 @@ NEVER_INLINE static const char* debugHookName(int debugHookID)
     return "";
 }
 
     return "";
 }
 
-static int locationForOffset(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset)
-{
-    return it - begin + offset;
-}
-
-static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)
+void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
 {
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
 
 {
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
 
-    printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str());
+    printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).c_str(), registerName(exec, r1).c_str());
 }
 
 }
 
-static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)
+void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
 {
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
     int r2 = (++it)->u.operand;
 {
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
     int r2 = (++it)->u.operand;
-    printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
+    printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str());
 }
 
 }
 
-static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op)
+void CodeBlock::printConditionalJump(ExecState* exec, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator& it, int location, const char* op) const
 {
     int r0 = (++it)->u.operand;
     int offset = (++it)->u.operand;
 {
     int r0 = (++it)->u.operand;
     int offset = (++it)->u.operand;
-    printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset));
+    printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(exec, r0).c_str(), offset, location + offset);
 }
 
 }
 
-static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)
+void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
 {
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
     int id0 = (++it)->u.operand;
 {
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
     int id0 = (++it)->u.operand;
-    printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
+    printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
     it += 4;
 }
 
     it += 4;
 }
 
-static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)
+void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
 {
     int r0 = (++it)->u.operand;
     int id0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
 {
     int r0 = (++it)->u.operand;
     int id0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
-    printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
+    printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str());
     it += 4;
 }
 
     it += 4;
 }
 
@@ -230,44 +228,44 @@ static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigne
 
 static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset)
 {
 
 static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset)
 {
-    switch (stubInfo.opcodeID) {
-    case op_get_by_id_self:
+    switch (stubInfo.accessType) {
+    case access_get_by_id_self:
         printf("  [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().c_str());
         return;
         printf("  [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().c_str());
         return;
-    case op_get_by_id_proto:
+    case access_get_by_id_proto:
         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().c_str());
         return;
         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().c_str());
         return;
-    case op_get_by_id_chain:
+    case access_get_by_id_chain:
         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().c_str());
         return;
         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().c_str());
         return;
-    case op_get_by_id_self_list:
+    case access_get_by_id_self_list:
         printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().c_str(), stubInfo.u.getByIdSelfList.listSize);
         return;
         printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().c_str(), stubInfo.u.getByIdSelfList.listSize);
         return;
-    case op_get_by_id_proto_list:
+    case access_get_by_id_proto_list:
         printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().c_str(), stubInfo.u.getByIdProtoList.listSize);
         return;
         printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().c_str(), stubInfo.u.getByIdProtoList.listSize);
         return;
-    case op_put_by_id_transition:
+    case access_put_by_id_transition:
         printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().c_str());
         return;
         printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().c_str());
         return;
-    case op_put_by_id_replace:
+    case access_put_by_id_replace:
         printf("  [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().c_str());
         return;
         printf("  [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().c_str());
         return;
-    case op_get_by_id:
+    case access_get_by_id:
         printf("  [%4d] %s\n", instructionOffset, "get_by_id");
         return;
         printf("  [%4d] %s\n", instructionOffset, "get_by_id");
         return;
-    case op_put_by_id:
+    case access_put_by_id:
         printf("  [%4d] %s\n", instructionOffset, "put_by_id");
         return;
         printf("  [%4d] %s\n", instructionOffset, "put_by_id");
         return;
-    case op_get_by_id_generic:
+    case access_get_by_id_generic:
         printf("  [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
         return;
         printf("  [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
         return;
-    case op_put_by_id_generic:
+    case access_put_by_id_generic:
         printf("  [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
         return;
         printf("  [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
         return;
-    case op_get_array_length:
+    case access_get_array_length:
         printf("  [%4d] %s\n", instructionOffset, "op_get_array_length");
         return;
         printf("  [%4d] %s\n", instructionOffset, "op_get_array_length");
         return;
-    case op_get_string_length:
+    case access_get_string_length:
         printf("  [%4d] %s\n", instructionOffset, "op_get_string_length");
         return;
     default:
         printf("  [%4d] %s\n", instructionOffset, "op_get_string_length");
         return;
     default:
@@ -360,7 +358,7 @@ void CodeBlock::dump(ExecState* exec) const
         unsigned registerIndex = m_numVars;
         size_t i = 0;
         do {
         unsigned registerIndex = m_numVars;
         size_t i = 0;
         do {
-            printf("   r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).ascii());
+            printf("   k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).ascii());
             ++i;
             ++registerIndex;
         } while (i < m_constantRegisters.size());
             ++i;
             ++registerIndex;
         } while (i < m_constantRegisters.size());
@@ -484,7 +482,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
         }
         case op_enter_with_activation: {
             int r0 = (++it)->u.operand;
         }
         case op_enter_with_activation: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str());
+            printf("[%4d] enter_with_activation %s\n", location, registerName(exec, r0).c_str());
             break;
         }
         case op_create_arguments: {
             break;
         }
         case op_create_arguments: {
@@ -497,148 +495,148 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
         }
         case op_convert_this: {
             int r0 = (++it)->u.operand;
         }
         case op_convert_this: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] convert_this %s\n", location, registerName(r0).c_str());
+            printf("[%4d] convert_this %s\n", location, registerName(exec, r0).c_str());
             break;
         }
         case op_new_object: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_new_object: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str());
+            printf("[%4d] new_object\t %s\n", location, registerName(exec, r0).c_str());
             break;
         }
         case op_new_array: {
             int dst = (++it)->u.operand;
             int argv = (++it)->u.operand;
             int argc = (++it)->u.operand;
             break;
         }
         case op_new_array: {
             int dst = (++it)->u.operand;
             int argv = (++it)->u.operand;
             int argc = (++it)->u.operand;
-            printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc);
+            printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(exec, dst).c_str(), registerName(exec, argv).c_str(), argc);
             break;
         }
         case op_new_regexp: {
             int r0 = (++it)->u.operand;
             int re0 = (++it)->u.operand;
             break;
         }
         case op_new_regexp: {
             int r0 = (++it)->u.operand;
             int re0 = (++it)->u.operand;
-            printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, regexp(re0)).c_str());
+            printf("[%4d] new_regexp\t %s, %s\n", location, registerName(exec, r0).c_str(), regexpName(re0, regexp(re0)).c_str());
             break;
         }
         case op_mov: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_mov: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
+            printf("[%4d] mov\t\t %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str());
             break;
         }
         case op_not: {
             break;
         }
         case op_not: {
-            printUnaryOp(location, it, "not");
+            printUnaryOp(exec, location, it, "not");
             break;
         }
         case op_eq: {
             break;
         }
         case op_eq: {
-            printBinaryOp(location, it, "eq");
+            printBinaryOp(exec, location, it, "eq");
             break;
         }
         case op_eq_null: {
             break;
         }
         case op_eq_null: {
-            printUnaryOp(location, it, "eq_null");
+            printUnaryOp(exec, location, it, "eq_null");
             break;
         }
         case op_neq: {
             break;
         }
         case op_neq: {
-            printBinaryOp(location, it, "neq");
+            printBinaryOp(exec, location, it, "neq");
             break;
         }
         case op_neq_null: {
             break;
         }
         case op_neq_null: {
-            printUnaryOp(location, it, "neq_null");
+            printUnaryOp(exec, location, it, "neq_null");
             break;
         }
         case op_stricteq: {
             break;
         }
         case op_stricteq: {
-            printBinaryOp(location, it, "stricteq");
+            printBinaryOp(exec, location, it, "stricteq");
             break;
         }
         case op_nstricteq: {
             break;
         }
         case op_nstricteq: {
-            printBinaryOp(location, it, "nstricteq");
+            printBinaryOp(exec, location, it, "nstricteq");
             break;
         }
         case op_less: {
             break;
         }
         case op_less: {
-            printBinaryOp(location, it, "less");
+            printBinaryOp(exec, location, it, "less");
             break;
         }
         case op_lesseq: {
             break;
         }
         case op_lesseq: {
-            printBinaryOp(location, it, "lesseq");
+            printBinaryOp(exec, location, it, "lesseq");
             break;
         }
         case op_pre_inc: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_pre_inc: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str());
+            printf("[%4d] pre_inc\t\t %s\n", location, registerName(exec, r0).c_str());
             break;
         }
         case op_pre_dec: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_pre_dec: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str());
+            printf("[%4d] pre_dec\t\t %s\n", location, registerName(exec, r0).c_str());
             break;
         }
         case op_post_inc: {
             break;
         }
         case op_post_inc: {
-            printUnaryOp(location, it, "post_inc");
+            printUnaryOp(exec, location, it, "post_inc");
             break;
         }
         case op_post_dec: {
             break;
         }
         case op_post_dec: {
-            printUnaryOp(location, it, "post_dec");
+            printUnaryOp(exec, location, it, "post_dec");
             break;
         }
         case op_to_jsnumber: {
             break;
         }
         case op_to_jsnumber: {
-            printUnaryOp(location, it, "to_jsnumber");
+            printUnaryOp(exec, location, it, "to_jsnumber");
             break;
         }
         case op_negate: {
             break;
         }
         case op_negate: {
-            printUnaryOp(location, it, "negate");
+            printUnaryOp(exec, location, it, "negate");
             break;
         }
         case op_add: {
             break;
         }
         case op_add: {
-            printBinaryOp(location, it, "add");
+            printBinaryOp(exec, location, it, "add");
             ++it;
             break;
         }
         case op_mul: {
             ++it;
             break;
         }
         case op_mul: {
-            printBinaryOp(location, it, "mul");
+            printBinaryOp(exec, location, it, "mul");
             ++it;
             break;
         }
         case op_div: {
             ++it;
             break;
         }
         case op_div: {
-            printBinaryOp(location, it, "div");
+            printBinaryOp(exec, location, it, "div");
             ++it;
             break;
         }
         case op_mod: {
             ++it;
             break;
         }
         case op_mod: {
-            printBinaryOp(location, it, "mod");
+            printBinaryOp(exec, location, it, "mod");
             break;
         }
         case op_sub: {
             break;
         }
         case op_sub: {
-            printBinaryOp(location, it, "sub");
+            printBinaryOp(exec, location, it, "sub");
             ++it;
             break;
         }
         case op_lshift: {
             ++it;
             break;
         }
         case op_lshift: {
-            printBinaryOp(location, it, "lshift");
+            printBinaryOp(exec, location, it, "lshift");
             break;            
         }
         case op_rshift: {
             break;            
         }
         case op_rshift: {
-            printBinaryOp(location, it, "rshift");
+            printBinaryOp(exec, location, it, "rshift");
             break;
         }
         case op_urshift: {
             break;
         }
         case op_urshift: {
-            printBinaryOp(location, it, "urshift");
+            printBinaryOp(exec, location, it, "urshift");
             break;
         }
         case op_bitand: {
             break;
         }
         case op_bitand: {
-            printBinaryOp(location, it, "bitand");
+            printBinaryOp(exec, location, it, "bitand");
             ++it;
             break;
         }
         case op_bitxor: {
             ++it;
             break;
         }
         case op_bitxor: {
-            printBinaryOp(location, it, "bitxor");
+            printBinaryOp(exec, location, it, "bitxor");
             ++it;
             break;
         }
         case op_bitor: {
             ++it;
             break;
         }
         case op_bitor: {
-            printBinaryOp(location, it, "bitor");
+            printBinaryOp(exec, location, it, "bitor");
             ++it;
             break;
         }
         case op_bitnot: {
             ++it;
             break;
         }
         case op_bitnot: {
-            printUnaryOp(location, it, "bitnot");
+            printUnaryOp(exec, location, it, "bitnot");
             break;
         }
         case op_instanceof: {
             break;
         }
         case op_instanceof: {
@@ -646,59 +644,59 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             int r3 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             int r3 = (++it)->u.operand;
-            printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str());
+            printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str(), registerName(exec, r3).c_str());
             break;
         }
         case op_typeof: {
             break;
         }
         case op_typeof: {
-            printUnaryOp(location, it, "typeof");
+            printUnaryOp(exec, location, it, "typeof");
             break;
         }
         case op_is_undefined: {
             break;
         }
         case op_is_undefined: {
-            printUnaryOp(location, it, "is_undefined");
+            printUnaryOp(exec, location, it, "is_undefined");
             break;
         }
         case op_is_boolean: {
             break;
         }
         case op_is_boolean: {
-            printUnaryOp(location, it, "is_boolean");
+            printUnaryOp(exec, location, it, "is_boolean");
             break;
         }
         case op_is_number: {
             break;
         }
         case op_is_number: {
-            printUnaryOp(location, it, "is_number");
+            printUnaryOp(exec, location, it, "is_number");
             break;
         }
         case op_is_string: {
             break;
         }
         case op_is_string: {
-            printUnaryOp(location, it, "is_string");
+            printUnaryOp(exec, location, it, "is_string");
             break;
         }
         case op_is_object: {
             break;
         }
         case op_is_object: {
-            printUnaryOp(location, it, "is_object");
+            printUnaryOp(exec, location, it, "is_object");
             break;
         }
         case op_is_function: {
             break;
         }
         case op_is_function: {
-            printUnaryOp(location, it, "is_function");
+            printUnaryOp(exec, location, it, "is_function");
             break;
         }
         case op_in: {
             break;
         }
         case op_in: {
-            printBinaryOp(location, it, "in");
+            printBinaryOp(exec, location, it, "in");
             break;
         }
         case op_resolve: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             break;
         }
         case op_resolve: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
-            printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
+            printf("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
             break;
         }
         case op_resolve_skip: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
             break;
         }
         case op_resolve_skip: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
-            printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels);
+            printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels);
             break;
         }
         case op_resolve_global: {
             int r0 = (++it)->u.operand;
             JSValue scope = JSValue((++it)->u.jsCell);
             int id0 = (++it)->u.operand;
             break;
         }
         case op_resolve_global: {
             int r0 = (++it)->u.operand;
             JSValue scope = JSValue((++it)->u.jsCell);
             int id0 = (++it)->u.operand;
-            printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str());
+            printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str());
             it += 2;
             break;
         }
             it += 2;
             break;
         }
@@ -706,244 +704,265 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int r0 = (++it)->u.operand;
             int index = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             int index = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
-            printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels);
+            printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).c_str(), index, skipLevels);
             break;
         }
         case op_put_scoped_var: {
             int index = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             break;
         }
         case op_put_scoped_var: {
             int index = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
             int r0 = (++it)->u.operand;
-            printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str());
+            printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(exec, r0).c_str());
             break;
         }
         case op_get_global_var: {
             int r0 = (++it)->u.operand;
             JSValue scope = JSValue((++it)->u.jsCell);
             int index = (++it)->u.operand;
             break;
         }
         case op_get_global_var: {
             int r0 = (++it)->u.operand;
             JSValue scope = JSValue((++it)->u.jsCell);
             int index = (++it)->u.operand;
-            printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index);
+            printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(exec, r0).c_str(), valueToSourceString(exec, scope).ascii(), index);
             break;
         }
         case op_put_global_var: {
             JSValue scope = JSValue((++it)->u.jsCell);
             int index = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             break;
         }
         case op_put_global_var: {
             JSValue scope = JSValue((++it)->u.jsCell);
             int index = (++it)->u.operand;
             int r0 = (++it)->u.operand;
-            printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str());
+            printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(exec, r0).c_str());
             break;
         }
         case op_resolve_base: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             break;
         }
         case op_resolve_base: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
-            printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
+            printf("[%4d] resolve_base\t %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
             break;
         }
         case op_resolve_with_base: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             break;
         }
         case op_resolve_with_base: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
-            printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
+            printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
             break;
         }
         case op_get_by_id: {
             break;
         }
         case op_get_by_id: {
-            printGetByIdOp(location, it, m_identifiers, "get_by_id");
+            printGetByIdOp(exec, location, it, "get_by_id");
             break;
         }
         case op_get_by_id_self: {
             break;
         }
         case op_get_by_id_self: {
-            printGetByIdOp(location, it, m_identifiers, "get_by_id_self");
+            printGetByIdOp(exec, location, it, "get_by_id_self");
             break;
         }
         case op_get_by_id_self_list: {
             break;
         }
         case op_get_by_id_self_list: {
-            printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list");
+            printGetByIdOp(exec, location, it, "get_by_id_self_list");
             break;
         }
         case op_get_by_id_proto: {
             break;
         }
         case op_get_by_id_proto: {
-            printGetByIdOp(location, it, m_identifiers, "get_by_id_proto");
+            printGetByIdOp(exec, location, it, "get_by_id_proto");
             break;
         }
         case op_get_by_id_proto_list: {
             break;
         }
         case op_get_by_id_proto_list: {
-            printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list");
+            printGetByIdOp(exec, location, it, "op_get_by_id_proto_list");
             break;
         }
         case op_get_by_id_chain: {
             break;
         }
         case op_get_by_id_chain: {
-            printGetByIdOp(location, it, m_identifiers, "get_by_id_chain");
+            printGetByIdOp(exec, location, it, "get_by_id_chain");
             break;
         }
         case op_get_by_id_generic: {
             break;
         }
         case op_get_by_id_generic: {
-            printGetByIdOp(location, it, m_identifiers, "get_by_id_generic");
+            printGetByIdOp(exec, location, it, "get_by_id_generic");
             break;
         }
         case op_get_array_length: {
             break;
         }
         case op_get_array_length: {
-            printGetByIdOp(location, it, m_identifiers, "get_array_length");
+            printGetByIdOp(exec, location, it, "get_array_length");
             break;
         }
         case op_get_string_length: {
             break;
         }
         case op_get_string_length: {
-            printGetByIdOp(location, it, m_identifiers, "get_string_length");
+            printGetByIdOp(exec, location, it, "get_string_length");
             break;
         }
         case op_put_by_id: {
             break;
         }
         case op_put_by_id: {
-            printPutByIdOp(location, it, m_identifiers, "put_by_id");
+            printPutByIdOp(exec, location, it, "put_by_id");
             break;
         }
         case op_put_by_id_replace: {
             break;
         }
         case op_put_by_id_replace: {
-            printPutByIdOp(location, it, m_identifiers, "put_by_id_replace");
+            printPutByIdOp(exec, location, it, "put_by_id_replace");
             break;
         }
         case op_put_by_id_transition: {
             break;
         }
         case op_put_by_id_transition: {
-            printPutByIdOp(location, it, m_identifiers, "put_by_id_transition");
+            printPutByIdOp(exec, location, it, "put_by_id_transition");
             break;
         }
         case op_put_by_id_generic: {
             break;
         }
         case op_put_by_id_generic: {
-            printPutByIdOp(location, it, m_identifiers, "put_by_id_generic");
+            printPutByIdOp(exec, location, it, "put_by_id_generic");
             break;
         }
         case op_put_getter: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_put_getter: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
+            printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str());
             break;
         }
         case op_put_setter: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_put_setter: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
+            printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str());
             break;
         }
         case op_method_check: {
             break;
         }
         case op_method_check: {
-            printf("[%4d] op_method_check\n", location);
+            printf("[%4d] method_check\n", location);
             break;
         }
         case op_del_by_id: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             break;
         }
         case op_del_by_id: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
-            printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
+            printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
             break;
         }
         case op_get_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             break;
         }
         case op_get_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
-            printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
+            printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str());
+            break;
+        }
+        case op_get_by_pname: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int r2 = (++it)->u.operand;
+            int r3 = (++it)->u.operand;
+            int r4 = (++it)->u.operand;
+            int r5 = (++it)->u.operand;
+            printf("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str(), registerName(exec, r3).c_str(), registerName(exec, r4).c_str(), registerName(exec, r5).c_str());
             break;
         }
         case op_put_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             break;
         }
         case op_put_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
-            printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
+            printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str());
             break;
         }
         case op_del_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             break;
         }
         case op_del_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
-            printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
+            printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str());
             break;
         }
         case op_put_by_index: {
             int r0 = (++it)->u.operand;
             unsigned n0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_put_by_index: {
             int r0 = (++it)->u.operand;
             unsigned n0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str());
+            printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(exec, r0).c_str(), n0, registerName(exec, r1).c_str());
             break;
         }
         case op_jmp: {
             int offset = (++it)->u.operand;
             break;
         }
         case op_jmp: {
             int offset = (++it)->u.operand;
-            printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));
+            printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, location + offset);
             break;
         }
         case op_loop: {
             int offset = (++it)->u.operand;
             break;
         }
         case op_loop: {
             int offset = (++it)->u.operand;
-            printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));
+            printf("[%4d] loop\t\t %d(->%d)\n", location, offset, location + offset);
             break;
         }
         case op_jtrue: {
             break;
         }
         case op_jtrue: {
-            printConditionalJump(begin, it, location, "jtrue");
+            printConditionalJump(exec, begin, it, location, "jtrue");
             break;
         }
         case op_loop_if_true: {
             break;
         }
         case op_loop_if_true: {
-            printConditionalJump(begin, it, location, "loop_if_true");
+            printConditionalJump(exec, begin, it, location, "loop_if_true");
+            break;
+        }
+        case op_loop_if_false: {
+            printConditionalJump(exec, begin, it, location, "loop_if_false");
             break;
         }
         case op_jfalse: {
             break;
         }
         case op_jfalse: {
-            printConditionalJump(begin, it, location, "jfalse");
+            printConditionalJump(exec, begin, it, location, "jfalse");
             break;
         }
         case op_jeq_null: {
             break;
         }
         case op_jeq_null: {
-            printConditionalJump(begin, it, location, "jeq_null");
+            printConditionalJump(exec, begin, it, location, "jeq_null");
             break;
         }
         case op_jneq_null: {
             break;
         }
         case op_jneq_null: {
-            printConditionalJump(begin, it, location, "jneq_null");
+            printConditionalJump(exec, begin, it, location, "jneq_null");
             break;
         }
         case op_jneq_ptr: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_jneq_ptr: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
+            printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset);
             break;
         }
         case op_jnless: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_jnless: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
+            printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset);
             break;
         }
         case op_jnlesseq: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_jnlesseq: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
+            printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset);
             break;
         }
         case op_loop_if_less: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_loop_if_less: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
+            printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset);
+            break;
+        }
+        case op_jless: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int offset = (++it)->u.operand;
+            printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset);
             break;
         }
         case op_loop_if_lesseq: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_loop_if_lesseq: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
+            printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset);
             break;
         }
         case op_switch_imm: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
             break;
         }
         case op_switch_imm: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
-            printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
+            printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).c_str());
             break;
         }
         case op_switch_char: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
             break;
         }
         case op_switch_char: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
-            printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
+            printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).c_str());
             break;
         }
         case op_switch_string: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
             break;
         }
         case op_switch_string: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
-            printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
+            printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).c_str());
             break;
         }
         case op_new_func: {
             int r0 = (++it)->u.operand;
             int f0 = (++it)->u.operand;
             break;
         }
         case op_new_func: {
             int r0 = (++it)->u.operand;
             int f0 = (++it)->u.operand;
-            printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0);
+            printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(exec, r0).c_str(), f0);
             break;
         }
         case op_new_func_exp: {
             int r0 = (++it)->u.operand;
             int f0 = (++it)->u.operand;
             break;
         }
         case op_new_func_exp: {
             int r0 = (++it)->u.operand;
             int f0 = (++it)->u.operand;
-            printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0);
+            printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(exec, r0).c_str(), f0);
             break;
         }
         case op_call: {
             break;
         }
         case op_call: {
@@ -951,7 +970,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int func = (++it)->u.operand;
             int argCount = (++it)->u.operand;
             int registerOffset = (++it)->u.operand;
             int func = (++it)->u.operand;
             int argCount = (++it)->u.operand;
             int registerOffset = (++it)->u.operand;
-            printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
+            printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(exec, dst).c_str(), registerName(exec, func).c_str(), argCount, registerOffset);
             break;
         }
         case op_call_eval: {
             break;
         }
         case op_call_eval: {
@@ -959,7 +978,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int func = (++it)->u.operand;
             int argCount = (++it)->u.operand;
             int registerOffset = (++it)->u.operand;
             int func = (++it)->u.operand;
             int argCount = (++it)->u.operand;
             int registerOffset = (++it)->u.operand;
-            printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
+            printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(exec, dst).c_str(), registerName(exec, func).c_str(), argCount, registerOffset);
             break;
         }
         case op_call_varargs: {
             break;
         }
         case op_call_varargs: {
@@ -967,16 +986,16 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int func = (++it)->u.operand;
             int argCount = (++it)->u.operand;
             int registerOffset = (++it)->u.operand;
             int func = (++it)->u.operand;
             int argCount = (++it)->u.operand;
             int registerOffset = (++it)->u.operand;
-            printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), registerName(argCount).c_str(), registerOffset);
+            printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(exec, dst).c_str(), registerName(exec, func).c_str(), registerName(exec, argCount).c_str(), registerOffset);
             break;
         }
         case op_load_varargs: {
             break;
         }
         case op_load_varargs: {
-            printUnaryOp(location, it, "load_varargs");
+            printUnaryOp(exec, location, it, "load_varargs");
             break;
         }
         case op_tear_off_activation: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_tear_off_activation: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str());
+            printf("[%4d] tear_off_activation\t %s\n", location, registerName(exec, r0).c_str());
             break;
         }
         case op_tear_off_arguments: {
             break;
         }
         case op_tear_off_arguments: {
@@ -985,7 +1004,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
         }
         case op_ret: {
             int r0 = (++it)->u.operand;
         }
         case op_ret: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str());
+            printf("[%4d] ret\t\t %s\n", location, registerName(exec, r0).c_str());
             break;
         }
         case op_construct: {
             break;
         }
         case op_construct: {
@@ -995,44 +1014,49 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int registerOffset = (++it)->u.operand;
             int proto = (++it)->u.operand;
             int thisRegister = (++it)->u.operand;
             int registerOffset = (++it)->u.operand;
             int proto = (++it)->u.operand;
             int thisRegister = (++it)->u.operand;
-            printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str());
+            printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(exec, dst).c_str(), registerName(exec, func).c_str(), argCount, registerOffset, registerName(exec, proto).c_str(), registerName(exec, thisRegister).c_str());
             break;
         }
         case op_construct_verify: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_construct_verify: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
+            printf("[%4d] construct_verify\t %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str());
             break;
         }
         case op_strcat: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int count = (++it)->u.operand;
             break;
         }
         case op_strcat: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int count = (++it)->u.operand;
-            printf("[%4d] op_strcat\t %s, %s, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), count);
+            printf("[%4d] strcat\t\t %s, %s, %d\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), count);
             break;
         }
         case op_to_primitive: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_to_primitive: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] op_to_primitive\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
+            printf("[%4d] to_primitive\t %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str());
             break;
         }
         case op_get_pnames: {
             break;
         }
         case op_get_pnames: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
+            int r0 = it[1].u.operand;
+            int r1 = it[2].u.operand;
+            int r2 = it[3].u.operand;
+            int r3 = it[4].u.operand;
+            int offset = it[5].u.operand;
+            printf("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str(), registerName(exec, r3).c_str(), offset, location + offset);
+            it += OPCODE_LENGTH(op_get_pnames) - 1;
             break;
         }
         case op_next_pname: {
             break;
         }
         case op_next_pname: {
-            int dest = (++it)->u.operand;
-            int iter = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset));
+            int dest = it[1].u.operand;
+            int iter = it[4].u.operand;
+            int offset = it[5].u.operand;
+            printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(exec, dest).c_str(), registerName(exec, iter).c_str(), offset, location + offset);
+            it += OPCODE_LENGTH(op_next_pname) - 1;
             break;
         }
         case op_push_scope: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_push_scope: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str());
+            printf("[%4d] push_scope\t %s\n", location, registerName(exec, r0).c_str());
             break;
         }
         case op_pop_scope: {
             break;
         }
         case op_pop_scope: {
@@ -1043,41 +1067,41 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
+            printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str());
             break;
         }
         case op_jmp_scopes: {
             int scopeDelta = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_jmp_scopes: {
             int scopeDelta = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset));
+            printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, location + offset);
             break;
         }
         case op_catch: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_catch: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str());
+            printf("[%4d] catch\t\t %s\n", location, registerName(exec, r0).c_str());
             break;
         }
         case op_throw: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_throw: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str());
+            printf("[%4d] throw\t\t %s\n", location, registerName(exec, r0).c_str());
             break;
         }
         case op_new_error: {
             int r0 = (++it)->u.operand;
             int errorType = (++it)->u.operand;
             int k0 = (++it)->u.operand;
             break;
         }
         case op_new_error: {
             int r0 = (++it)->u.operand;
             int errorType = (++it)->u.operand;
             int k0 = (++it)->u.operand;
-            printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, getConstant(k0)).c_str());
+            printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(exec, r0).c_str(), errorType, constantName(exec, k0, getConstant(k0)).c_str());
             break;
         }
         case op_jsr: {
             int retAddrDst = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_jsr: {
             int retAddrDst = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset));
+            printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(exec, retAddrDst).c_str(), offset, location + offset);
             break;
         }
         case op_sret: {
             int retAddrSrc = (++it)->u.operand;
             break;
         }
         case op_sret: {
             int retAddrSrc = (++it)->u.operand;
-            printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str());
+            printf("[%4d] sret\t\t %s\n", location, registerName(exec, retAddrSrc).c_str());
             break;
         }
         case op_debug: {
             break;
         }
         case op_debug: {
@@ -1089,17 +1113,17 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
         }
         case op_profile_will_call: {
             int function = (++it)->u.operand;
         }
         case op_profile_will_call: {
             int function = (++it)->u.operand;
-            printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str());
+            printf("[%4d] profile_will_call %s\n", location, registerName(exec, function).c_str());
             break;
         }
         case op_profile_did_call: {
             int function = (++it)->u.operand;
             break;
         }
         case op_profile_did_call: {
             int function = (++it)->u.operand;
-            printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str());
+            printf("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).c_str());
             break;
         }
         case op_end: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_end: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str());
+            printf("[%4d] end\t\t %s\n", location, registerName(exec, r0).c_str());
             break;
         }
     }
             break;
         }
     }
@@ -1246,43 +1270,22 @@ void CodeBlock::dumpStatistics()
 #endif
 }
 
 #endif
 }
 
-CodeBlock::CodeBlock(ScopeNode* ownerNode)
+CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab)
     : m_numCalleeRegisters(0)
     , m_numVars(0)
     , m_numParameters(0)
     : m_numCalleeRegisters(0)
     , m_numVars(0)
     , m_numParameters(0)
-    , m_ownerNode(ownerNode)
+    , m_ownerExecutable(ownerExecutable)
     , m_globalData(0)
 #ifndef NDEBUG
     , m_instructionCount(0)
 #endif
     , m_globalData(0)
 #ifndef NDEBUG
     , m_instructionCount(0)
 #endif
-    , m_needsFullScopeChain(false)
-    , m_usesEval(false)
-    , m_isNumericCompareFunction(false)
-    , m_codeType(NativeCode)
-    , m_source(0)
-    , m_sourceOffset(0)
-    , m_exceptionInfo(0)
-{
-#if DUMP_CODE_BLOCK_STATISTICS
-    liveCodeBlockSet.add(this);
-#endif
-}
-
-CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
-    : m_numCalleeRegisters(0)
-    , m_numVars(0)
-    , m_numParameters(0)
-    , m_ownerNode(ownerNode)
-    , m_globalData(0)
-#ifndef NDEBUG
-    , m_instructionCount(0)
-#endif
-    , m_needsFullScopeChain(ownerNode->needsActivation())
-    , m_usesEval(ownerNode->usesEval())
+    , m_needsFullScopeChain(ownerExecutable->needsActivation())
+    , m_usesEval(ownerExecutable->usesEval())
     , m_isNumericCompareFunction(false)
     , m_codeType(codeType)
     , m_source(sourceProvider)
     , m_sourceOffset(sourceOffset)
     , m_isNumericCompareFunction(false)
     , m_codeType(codeType)
     , m_source(sourceProvider)
     , m_sourceOffset(sourceOffset)
+    , m_symbolTable(symTab)
     , m_exceptionInfo(new ExceptionInfo)
 {
     ASSERT(m_source);
     , m_exceptionInfo(new ExceptionInfo)
 {
     ASSERT(m_source);
@@ -1319,7 +1322,7 @@ CodeBlock::~CodeBlock()
         if (Structure* structure = m_methodCallLinkInfos[i].cachedStructure) {
             structure->deref();
             // Both members must be filled at the same time
         if (Structure* structure = m_methodCallLinkInfos[i].cachedStructure) {
             structure->deref();
             // Both members must be filled at the same time
-            ASSERT(m_methodCallLinkInfos[i].cachedPrototypeStructure);
+            ASSERT(!!m_methodCallLinkInfos[i].cachedPrototypeStructure);
             m_methodCallLinkInfos[i].cachedPrototypeStructure->deref();
         }
     }
             m_methodCallLinkInfos[i].cachedPrototypeStructure->deref();
         }
     }
@@ -1350,7 +1353,6 @@ void CodeBlock::unlinkCallers()
 
 void CodeBlock::derefStructures(Instruction* vPC) const
 {
 
 void CodeBlock::derefStructures(Instruction* vPC) const
 {
-    ASSERT(m_codeType != NativeCode);
     Interpreter* interpreter = m_globalData->interpreter;
 
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
     Interpreter* interpreter = m_globalData->interpreter;
 
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
@@ -1396,7 +1398,6 @@ void CodeBlock::derefStructures(Instruction* vPC) const
 
 void CodeBlock::refStructures(Instruction* vPC) const
 {
 
 void CodeBlock::refStructures(Instruction* vPC) const
 {
-    ASSERT(m_codeType != NativeCode);
     Interpreter* interpreter = m_globalData->interpreter;
 
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
     Interpreter* interpreter = m_globalData->interpreter;
 
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
@@ -1428,26 +1429,18 @@ void CodeBlock::refStructures(Instruction* vPC) const
     ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic));
 }
 
     ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic));
 }
 
-void CodeBlock::mark()
+void CodeBlock::markAggregate(MarkStack& markStack)
 {
     for (size_t i = 0; i < m_constantRegisters.size(); ++i)
 {
     for (size_t i = 0; i < m_constantRegisters.size(); ++i)
-        if (!m_constantRegisters[i].marked())
-            m_constantRegisters[i].mark();
-
-    for (size_t i = 0; i < m_functionExpressions.size(); ++i)
-        m_functionExpressions[i]->body()->mark();
-
-    if (m_rareData) {
-        for (size_t i = 0; i < m_rareData->m_functions.size(); ++i)
-            m_rareData->m_functions[i]->body()->mark();
-
-        m_rareData->m_evalCodeCache.mark();
-    }
+        markStack.append(m_constantRegisters[i].jsValue());
+    for (size_t i = 0; i < m_functionExprs.size(); ++i)
+        m_functionExprs[i]->markAggregate(markStack);
+    for (size_t i = 0; i < m_functionDecls.size(); ++i)
+        m_functionDecls[i]->markAggregate(markStack);
 }
 
 void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
 {
 }
 
 void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
 {
-    ASSERT(m_codeType != NativeCode);
     if (m_exceptionInfo)
         return;
 
     if (m_exceptionInfo)
         return;
 
@@ -1464,61 +1457,11 @@ void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
             scopeChain = scopeChain->next;
     }
 
             scopeChain = scopeChain->next;
     }
 
-    switch (m_codeType) {
-        case FunctionCode: {
-            FunctionBodyNode* ownerFunctionBodyNode = static_cast<FunctionBodyNode*>(m_ownerNode);
-            RefPtr<FunctionBodyNode> newFunctionBody = m_globalData->parser->reparse<FunctionBodyNode>(m_globalData, ownerFunctionBodyNode);
-            ASSERT(newFunctionBody);
-            newFunctionBody->finishParsing(ownerFunctionBodyNode->copyParameters(), ownerFunctionBodyNode->parameterCount());
-
-            m_globalData->scopeNodeBeingReparsed = newFunctionBody.get();
-
-            CodeBlock& newCodeBlock = newFunctionBody->bytecodeForExceptionInfoReparse(scopeChain, this);
-            ASSERT(newCodeBlock.m_exceptionInfo);
-            ASSERT(newCodeBlock.m_instructionCount == m_instructionCount);
-
-#if ENABLE(JIT)
-            JIT::compile(m_globalData, &newCodeBlock);
-            ASSERT(newFunctionBody->generatedJITCode().size() == ownerNode()->generatedJITCode().size());
-#endif
-
-            m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release());
-
-            m_globalData->scopeNodeBeingReparsed = 0;
-
-            break;
-        }
-        case EvalCode: {
-            EvalNode* ownerEvalNode = static_cast<EvalNode*>(m_ownerNode);
-            RefPtr<EvalNode> newEvalBody = m_globalData->parser->reparse<EvalNode>(m_globalData, ownerEvalNode);
-
-            m_globalData->scopeNodeBeingReparsed = newEvalBody.get();
-
-            EvalCodeBlock& newCodeBlock = newEvalBody->bytecodeForExceptionInfoReparse(scopeChain, this);
-            ASSERT(newCodeBlock.m_exceptionInfo);
-            ASSERT(newCodeBlock.m_instructionCount == m_instructionCount);
-
-#if ENABLE(JIT)
-            JIT::compile(m_globalData, &newCodeBlock);
-            ASSERT(newEvalBody->generatedJITCode().size() == ownerNode()->generatedJITCode().size());
-#endif
-
-            m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release());
-
-            m_globalData->scopeNodeBeingReparsed = 0;
-
-            break;
-        }
-        default:
-            // CodeBlocks for Global code blocks are transient and therefore to not gain from 
-            // from throwing out there exception information.
-            ASSERT_NOT_REACHED();
-    }
+    m_exceptionInfo.set(m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this));
 }
 
 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
 {
 }
 
 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
 {
-    ASSERT(m_codeType != NativeCode);
     ASSERT(bytecodeOffset < m_instructionCount);
 
     if (!m_rareData)
     ASSERT(bytecodeOffset < m_instructionCount);
 
     if (!m_rareData)
@@ -1537,14 +1480,13 @@ HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
 
 int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset)
 {
 
 int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset)
 {
-    ASSERT(m_codeType != NativeCode);
     ASSERT(bytecodeOffset < m_instructionCount);
 
     reparseForExceptionInfoIfNecessary(callFrame);
     ASSERT(m_exceptionInfo);
 
     if (!m_exceptionInfo->m_lineInfo.size())
     ASSERT(bytecodeOffset < m_instructionCount);
 
     reparseForExceptionInfoIfNecessary(callFrame);
     ASSERT(m_exceptionInfo);
 
     if (!m_exceptionInfo->m_lineInfo.size())
-        return m_ownerNode->source().firstLine(); // Empty function
+        return m_ownerExecutable->source().firstLine(); // Empty function
 
     int low = 0;
     int high = m_exceptionInfo->m_lineInfo.size();
 
     int low = 0;
     int high = m_exceptionInfo->m_lineInfo.size();
@@ -1557,13 +1499,12 @@ int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned byteco
     }
     
     if (!low)
     }
     
     if (!low)
-        return m_ownerNode->source().firstLine();
+        return m_ownerExecutable->source().firstLine();
     return m_exceptionInfo->m_lineInfo[low - 1].lineNumber;
 }
 
 int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
 {
     return m_exceptionInfo->m_lineInfo[low - 1].lineNumber;
 }
 
 int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
 {
-    ASSERT(m_codeType != NativeCode);
     ASSERT(bytecodeOffset < m_instructionCount);
 
     reparseForExceptionInfoIfNecessary(callFrame);
     ASSERT(bytecodeOffset < m_instructionCount);
 
     reparseForExceptionInfoIfNecessary(callFrame);
@@ -1603,7 +1544,6 @@ int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned b
 
 bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID)
 {
 
 bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID)
 {
-    ASSERT(m_codeType != NativeCode);
     ASSERT(bytecodeOffset < m_instructionCount);
 
     reparseForExceptionInfoIfNecessary(callFrame);
     ASSERT(bytecodeOffset < m_instructionCount);
 
     reparseForExceptionInfoIfNecessary(callFrame);
@@ -1632,7 +1572,6 @@ bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsi
 #if ENABLE(JIT)
 bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex)
 {
 #if ENABLE(JIT)
 bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex)
 {
-    ASSERT(m_codeType != NativeCode);
     ASSERT(bytecodeOffset < m_instructionCount);
 
     if (!m_rareData || !m_rareData->m_functionRegisterInfos.size())
     ASSERT(bytecodeOffset < m_instructionCount);
 
     if (!m_rareData || !m_rareData->m_functionRegisterInfos.size())
@@ -1659,7 +1598,6 @@ bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int&
 #if !ENABLE(JIT)
 bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
 {
 #if !ENABLE(JIT)
 bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
 {
-    ASSERT(m_codeType != NativeCode);
     if (m_globalResolveInstructions.isEmpty())
         return false;
 
     if (m_globalResolveInstructions.isEmpty())
         return false;
 
@@ -1680,7 +1618,6 @@ bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOff
 #else
 bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
 {
 #else
 bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
 {
-    ASSERT(m_codeType != NativeCode);
     if (m_globalResolveInfos.isEmpty())
         return false;
 
     if (m_globalResolveInfos.isEmpty())
         return false;
 
@@ -1700,18 +1637,6 @@ bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
 }
 #endif
 
 }
 #endif
 
-#if ENABLE(JIT)
-void CodeBlock::setJITCode(JITCode jitCode)
-{
-    ASSERT(m_codeType != NativeCode); 
-    ownerNode()->setJITCode(jitCode);
-#if !ENABLE(OPCODE_SAMPLING)
-    if (!BytecodeGenerator::dumpsGeneratedCode())
-        m_instructions.clear();
-#endif
-}
-#endif
-
 void CodeBlock::shrinkToFit()
 {
     m_instructions.shrinkToFit();
 void CodeBlock::shrinkToFit()
 {
     m_instructions.shrinkToFit();
@@ -1727,7 +1652,8 @@ void CodeBlock::shrinkToFit()
 #endif
 
     m_identifiers.shrinkToFit();
 #endif
 
     m_identifiers.shrinkToFit();
-    m_functionExpressions.shrinkToFit();
+    m_functionDecls.shrinkToFit();
+    m_functionExprs.shrinkToFit();
     m_constantRegisters.shrinkToFit();
 
     if (m_exceptionInfo) {
     m_constantRegisters.shrinkToFit();
 
     if (m_exceptionInfo) {
@@ -1738,7 +1664,6 @@ void CodeBlock::shrinkToFit()
 
     if (m_rareData) {
         m_rareData->m_exceptionHandlers.shrinkToFit();
 
     if (m_rareData) {
         m_rareData->m_exceptionHandlers.shrinkToFit();
-        m_rareData->m_functions.shrinkToFit();
         m_rareData->m_regexps.shrinkToFit();
         m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
         m_rareData->m_characterSwitchJumpTables.shrinkToFit();
         m_rareData->m_regexps.shrinkToFit();
         m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
         m_rareData->m_characterSwitchJumpTables.shrinkToFit();
index eaf5d1d2679fffb3be9438f64723d484bc374ad5..eb874cc4c17b8a39a270f3c0d746e0641c72e819 100644 (file)
@@ -36,6 +36,7 @@
 #include "JSGlobalObject.h"
 #include "JumpTable.h"
 #include "Nodes.h"
 #include "JSGlobalObject.h"
 #include "JumpTable.h"
 #include "Nodes.h"
+#include "PtrAndFlags.h"
 #include "RegExp.h"
 #include "UString.h"
 #include <wtf/FastAllocBase.h>
 #include "RegExp.h"
 #include "UString.h"
 #include <wtf/FastAllocBase.h>
@@ -54,9 +55,13 @@ static const int FirstConstantRegisterIndex = 0x40000000;
 
 namespace JSC {
 
 
 namespace JSC {
 
+    enum HasSeenShouldRepatch {
+        hasSeenShouldRepatch
+    };
+
     class ExecState;
 
     class ExecState;
 
-    enum CodeType { GlobalCode, EvalCode, FunctionCode, NativeCode };
+    enum CodeType { GlobalCode, EvalCode, FunctionCode };
 
     static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
 
 
     static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
 
@@ -105,25 +110,44 @@ namespace JSC {
         CodeLocationNearCall callReturnLocation;
         CodeLocationDataLabelPtr hotPathBegin;
         CodeLocationNearCall hotPathOther;
         CodeLocationNearCall callReturnLocation;
         CodeLocationDataLabelPtr hotPathBegin;
         CodeLocationNearCall hotPathOther;
-        CodeBlock* ownerCodeBlock;
+        PtrAndFlags<CodeBlock, HasSeenShouldRepatch> ownerCodeBlock;
         CodeBlock* callee;
         unsigned position;
         
         void setUnlinked() { callee = 0; }
         bool isLinked() { return callee; }
         CodeBlock* callee;
         unsigned position;
         
         void setUnlinked() { callee = 0; }
         bool isLinked() { return callee; }
+
+        bool seenOnce()
+        {
+            return ownerCodeBlock.isFlagSet(hasSeenShouldRepatch);
+        }
+
+        void setSeen()
+        {
+            ownerCodeBlock.setFlag(hasSeenShouldRepatch);
+        }
     };
 
     struct MethodCallLinkInfo {
         MethodCallLinkInfo()
             : cachedStructure(0)
     };
 
     struct MethodCallLinkInfo {
         MethodCallLinkInfo()
             : cachedStructure(0)
-            , cachedPrototypeStructure(0)
         {
         }
 
         {
         }
 
+        bool seenOnce()
+        {
+            return cachedPrototypeStructure.isFlagSet(hasSeenShouldRepatch);
+        }
+
+        void setSeen()
+        {
+            cachedPrototypeStructure.setFlag(hasSeenShouldRepatch);
+        }
+
         CodeLocationCall callReturnLocation;
         CodeLocationDataLabelPtr structureLabel;
         Structure* cachedStructure;
         CodeLocationCall callReturnLocation;
         CodeLocationDataLabelPtr structureLabel;
         Structure* cachedStructure;
-        Structure* cachedPrototypeStructure;
+        PtrAndFlags<Structure, HasSeenShouldRepatch> cachedPrototypeStructure;
     };
 
     struct FunctionRegisterInfo {
     };
 
     struct FunctionRegisterInfo {
@@ -224,14 +248,24 @@ namespace JSC {
     }
 #endif
 
     }
 #endif
 
-    class CodeBlock : public WTF::FastAllocBase {
+    struct ExceptionInfo : FastAllocBase {
+        Vector<ExpressionRangeInfo> m_expressionInfo;
+        Vector<LineInfo> m_lineInfo;
+        Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo;
+
+#if ENABLE(JIT)
+        Vector<CallReturnOffsetToBytecodeIndex> m_callReturnIndexVector;
+#endif
+    };
+
+    class CodeBlock : public FastAllocBase {
         friend class JIT;
         friend class JIT;
+    protected:
+        CodeBlock(ScriptExecutable* ownerExecutable, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset, SymbolTable* symbolTable);
     public:
     public:
-        CodeBlock(ScopeNode* ownerNode);
-        CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset);
-        ~CodeBlock();
+        virtual ~CodeBlock();
 
 
-        void mark();
+        void markAggregate(MarkStack&);
         void refStructures(Instruction* vPC) const;
         void derefStructures(Instruction* vPC) const;
 #if ENABLE(JIT_OPTIMIZE_CALL)
         void refStructures(Instruction* vPC) const;
         void derefStructures(Instruction* vPC) const;
 #if ENABLE(JIT_OPTIMIZE_CALL)
@@ -305,7 +339,7 @@ namespace JSC {
         unsigned getBytecodeIndex(CallFrame* callFrame, ReturnAddressPtr returnAddress)
         {
             reparseForExceptionInfoIfNecessary(callFrame);
         unsigned getBytecodeIndex(CallFrame* callFrame, ReturnAddressPtr returnAddress)
         {
             reparseForExceptionInfoIfNecessary(callFrame);
-            return binaryChop<CallReturnOffsetToBytecodeIndex, unsigned, getCallReturnOffset>(m_exceptionInfo->m_callReturnIndexVector.begin(), m_exceptionInfo->m_callReturnIndexVector.size(), ownerNode()->generatedJITCode().offsetOf(returnAddress.value()))->bytecodeIndex;
+            return binaryChop<CallReturnOffsetToBytecodeIndex, unsigned, getCallReturnOffset>(callReturnIndexVector().begin(), callReturnIndexVector().size(), ownerExecutable()->generatedJITCode().offsetOf(returnAddress.value()))->bytecodeIndex;
         }
         
         bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex);
         }
         
         bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex);
@@ -315,17 +349,19 @@ namespace JSC {
         bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
 
         Vector<Instruction>& instructions() { return m_instructions; }
         bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
 
         Vector<Instruction>& instructions() { return m_instructions; }
+        void discardBytecode() { m_instructions.clear(); }
+
 #ifndef NDEBUG
 #ifndef NDEBUG
+        unsigned instructionCount() { return m_instructionCount; }
         void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; }
 #endif
 
 #if ENABLE(JIT)
         void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; }
 #endif
 
 #if ENABLE(JIT)
-        JITCode& getJITCode() { return ownerNode()->generatedJITCode(); }
-        void setJITCode(JITCode);
-        ExecutablePool* executablePool() { return ownerNode()->getExecutablePool(); }
+        JITCode& getJITCode() { return ownerExecutable()->generatedJITCode(); }
+        ExecutablePool* executablePool() { return ownerExecutable()->getExecutablePool(); }
 #endif
 
 #endif
 
-        ScopeNode* ownerNode() const { return m_ownerNode; }
+        ScriptExecutable* ownerExecutable() const { return m_ownerExecutable; }
 
         void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
 
 
         void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
 
@@ -341,8 +377,8 @@ namespace JSC {
 
         CodeType codeType() const { return m_codeType; }
 
 
         CodeType codeType() const { return m_codeType; }
 
-        SourceProvider* source() const { ASSERT(m_codeType != NativeCode); return m_source.get(); }
-        unsigned sourceOffset() const { ASSERT(m_codeType != NativeCode); return m_sourceOffset; }
+        SourceProvider* source() const { return m_source.get(); }
+        unsigned sourceOffset() const { return m_sourceOffset; }
 
         size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
         void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
 
         size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
         void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
@@ -380,6 +416,7 @@ namespace JSC {
 
         bool hasExceptionInfo() const { return m_exceptionInfo; }
         void clearExceptionInfo() { m_exceptionInfo.clear(); }
 
         bool hasExceptionInfo() const { return m_exceptionInfo; }
         void clearExceptionInfo() { m_exceptionInfo.clear(); }
+        ExceptionInfo* extractExceptionInfo() { ASSERT(m_exceptionInfo); return m_exceptionInfo.release(); }
 
         void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); }
         void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); }
 
         void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); }
         void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); }
@@ -401,16 +438,14 @@ namespace JSC {
         size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
         void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); }
         Register& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
         size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
         void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); }
         Register& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
-        ALWAYS_INLINE bool isConstantRegisterIndex(int index) { return index >= FirstConstantRegisterIndex; }
+        ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
         ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].jsValue(); }
 
         ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].jsValue(); }
 
-        unsigned addFunctionExpression(FuncExprNode* n) { unsigned size = m_functionExpressions.size(); m_functionExpressions.append(n); return size; }
-        FuncExprNode* functionExpression(int index) const { return m_functionExpressions[index].get(); }
-
-        unsigned addFunction(FuncDeclNode* n) { createRareDataIfNecessary(); unsigned size = m_rareData->m_functions.size(); m_rareData->m_functions.append(n); return size; }
-        FuncDeclNode* function(int index) const { ASSERT(m_rareData); return m_rareData->m_functions[index].get(); }
-
-        bool hasFunctions() const { return m_functionExpressions.size() || (m_rareData && m_rareData->m_functions.size()); }
+        unsigned addFunctionDecl(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionDecls.size(); m_functionDecls.append(n); return size; }
+        FunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
+        int numberOfFunctionDecls() { return m_functionDecls.size(); }
+        unsigned addFunctionExpr(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionExprs.size(); m_functionExprs.append(n); return size; }
+        FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
 
         unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; }
         RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
 
         unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; }
         RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
@@ -431,9 +466,10 @@ namespace JSC {
         StringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
 
 
         StringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
 
 
-        SymbolTable& symbolTable() { return m_symbolTable; }
+        SymbolTable* symbolTable() { return m_symbolTable; }
+        SharedSymbolTable* sharedSymbolTable() { ASSERT(m_codeType == FunctionCode); return static_cast<SharedSymbolTable*>(m_symbolTable); }
 
 
-        EvalCodeCache& evalCodeCache() { ASSERT(m_codeType != NativeCode); createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
+        EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
 
         void shrinkToFit();
 
 
         void shrinkToFit();
 
@@ -446,18 +482,24 @@ namespace JSC {
     private:
 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
         void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
     private:
 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
         void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
+
+        CString registerName(ExecState*, int r) const;
+        void printUnaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
+        void printBinaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
+        void printConditionalJump(ExecState*, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator&, int location, const char* op) const;
+        void printGetByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
+        void printPutByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
 #endif
 
         void reparseForExceptionInfoIfNecessary(CallFrame*);
 
         void createRareDataIfNecessary()
         {
 #endif
 
         void reparseForExceptionInfoIfNecessary(CallFrame*);
 
         void createRareDataIfNecessary()
         {
-            ASSERT(m_codeType != NativeCode); 
             if (!m_rareData)
                 m_rareData.set(new RareData);
         }
 
             if (!m_rareData)
                 m_rareData.set(new RareData);
         }
 
-        ScopeNode* m_ownerNode;
+        ScriptExecutable* m_ownerExecutable;
         JSGlobalData* m_globalData;
 
         Vector<Instruction> m_instructions;
         JSGlobalData* m_globalData;
 
         Vector<Instruction> m_instructions;
@@ -493,26 +535,17 @@ namespace JSC {
         // Constant Pool
         Vector<Identifier> m_identifiers;
         Vector<Register> m_constantRegisters;
         // Constant Pool
         Vector<Identifier> m_identifiers;
         Vector<Register> m_constantRegisters;
-        Vector<RefPtr<FuncExprNode> > m_functionExpressions;
-
-        SymbolTable m_symbolTable;
+        Vector<RefPtr<FunctionExecutable> > m_functionDecls;
+        Vector<RefPtr<FunctionExecutable> > m_functionExprs;
 
 
-        struct ExceptionInfo {
-            Vector<ExpressionRangeInfo> m_expressionInfo;
-            Vector<LineInfo> m_lineInfo;
-            Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo;
+        SymbolTable* m_symbolTable;
 
 
-#if ENABLE(JIT)
-            Vector<CallReturnOffsetToBytecodeIndex> m_callReturnIndexVector;
-#endif
-        };
         OwnPtr<ExceptionInfo> m_exceptionInfo;
 
         OwnPtr<ExceptionInfo> m_exceptionInfo;
 
-        struct RareData {
+        struct RareData : FastAllocBase {
             Vector<HandlerInfo> m_exceptionHandlers;
 
             // Rare Constants
             Vector<HandlerInfo> m_exceptionHandlers;
 
             // Rare Constants
-            Vector<RefPtr<FuncDeclNode> > m_functions;
             Vector<RefPtr<RegExp> > m_regexps;
 
             // Jump Tables
             Vector<RefPtr<RegExp> > m_regexps;
 
             // Jump Tables
@@ -532,16 +565,16 @@ namespace JSC {
     // Program code is not marked by any function, so we make the global object
     // responsible for marking it.
 
     // Program code is not marked by any function, so we make the global object
     // responsible for marking it.
 
-    class ProgramCodeBlock : public CodeBlock {
+    class GlobalCodeBlock : public CodeBlock {
     public:
     public:
-        ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
-            : CodeBlock(ownerNode, codeType, sourceProvider, 0)
+        GlobalCodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, JSGlobalObject* globalObject)
+            : CodeBlock(ownerExecutable, codeType, sourceProvider, sourceOffset, &m_unsharedSymbolTable)
             , m_globalObject(globalObject)
         {
             m_globalObject->codeBlocks().add(this);
         }
 
             , m_globalObject(globalObject)
         {
             m_globalObject->codeBlocks().add(this);
         }
 
-        ~ProgramCodeBlock()
+        ~GlobalCodeBlock()
         {
             if (m_globalObject)
                 m_globalObject->codeBlocks().remove(this);
         {
             if (m_globalObject)
                 m_globalObject->codeBlocks().remove(this);
@@ -551,20 +584,54 @@ namespace JSC {
 
     private:
         JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.
 
     private:
         JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.
+        SymbolTable m_unsharedSymbolTable;
+    };
+
+    class ProgramCodeBlock : public GlobalCodeBlock {
+    public:
+        ProgramCodeBlock(ProgramExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
+            : GlobalCodeBlock(ownerExecutable, codeType, sourceProvider, 0, globalObject)
+        {
+        }
     };
 
     };
 
-    class EvalCodeBlock : public ProgramCodeBlock {
+    class EvalCodeBlock : public GlobalCodeBlock {
     public:
     public:
-        EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
-            : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider)
+        EvalCodeBlock(EvalExecutable* ownerExecutable, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
+            : GlobalCodeBlock(ownerExecutable, EvalCode, sourceProvider, 0, globalObject)
             , m_baseScopeDepth(baseScopeDepth)
         {
         }
 
         int baseScopeDepth() const { return m_baseScopeDepth; }
 
             , m_baseScopeDepth(baseScopeDepth)
         {
         }
 
         int baseScopeDepth() const { return m_baseScopeDepth; }
 
+        const Identifier& variable(unsigned index) { return m_variables[index]; }
+        unsigned numVariables() { return m_variables.size(); }
+        void adoptVariables(Vector<Identifier>& variables)
+        {
+            ASSERT(m_variables.isEmpty());
+            m_variables.swap(variables);
+        }
+
     private:
         int m_baseScopeDepth;
     private:
         int m_baseScopeDepth;
+        Vector<Identifier> m_variables;
+    };
+
+    class FunctionCodeBlock : public CodeBlock {
+    public:
+        // Rather than using the usual RefCounted::create idiom for SharedSymbolTable we just use new
+        // as we need to initialise the CodeBlock before we could initialise any RefPtr to hold the shared
+        // symbol table, so we just pass as a raw pointer with a ref count of 1.  We then manually deref
+        // in the destructor.
+        FunctionCodeBlock(FunctionExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
+            : CodeBlock(ownerExecutable, codeType, sourceProvider, sourceOffset, new SharedSymbolTable)
+        {
+        }
+        ~FunctionCodeBlock()
+        {
+            sharedSymbolTable()->deref();
+        }
     };
 
     inline Register& ExecState::r(int index)
     };
 
     inline Register& ExecState::r(int index)
index f0ce73e9531263f30e1092f505d45e83c029ceaf..05834fcbfe24e27e6f11148e16ac471234f2fe71 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef EvalCodeCache_h
 #define EvalCodeCache_h
 
 #ifndef EvalCodeCache_h
 #define EvalCodeCache_h
 
+#include "Executable.h"
 #include "JSGlobalObject.h"
 #include "Nodes.h"
 #include "Parser.h"
 #include "JSGlobalObject.h"
 #include "Nodes.h"
 #include "Parser.h"
@@ -41,44 +42,33 @@ namespace JSC {
 
     class EvalCodeCache {
     public:
 
     class EvalCodeCache {
     public:
-        PassRefPtr<EvalNode> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
+        PassRefPtr<EvalExecutable> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
         {
         {
-            RefPtr<EvalNode> evalNode;
+            RefPtr<EvalExecutable> evalExecutable;
 
             if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
 
             if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
-                evalNode = m_cacheMap.get(evalSource.rep());
+                evalExecutable = m_cacheMap.get(evalSource.rep());
 
 
-            if (!evalNode) {
-                int errorLine;
-                UString errorMessage;
-                
-                SourceCode source = makeSource(evalSource);
-                evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errorLine, &errorMessage);
-                if (evalNode) {
-                    if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
-                        m_cacheMap.set(evalSource.rep(), evalNode);
-                } else {
-                    exceptionValue = Error::create(exec, SyntaxError, errorMessage, errorLine, source.provider()->asID(), 0);
+            if (!evalExecutable) {
+                evalExecutable = EvalExecutable::create(exec, makeSource(evalSource));
+                exceptionValue = evalExecutable->compile(exec, scopeChain);
+                if (exceptionValue)
                     return 0;
                     return 0;
-                }
+
+                if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
+                    m_cacheMap.set(evalSource.rep(), evalExecutable);
             }
 
             }
 
-            return evalNode.release();
+            return evalExecutable.release();
         }
 
         bool isEmpty() const { return m_cacheMap.isEmpty(); }
 
         }
 
         bool isEmpty() const { return m_cacheMap.isEmpty(); }
 
-        void mark()
-        {
-            EvalCacheMap::iterator end = m_cacheMap.end();
-            for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
-                ptr->second->mark();
-        }
     private:
         static const int maxCacheableSourceLength = 256;
         static const int maxCacheEntries = 64;
 
     private:
         static const int maxCacheableSourceLength = 256;
         static const int maxCacheEntries = 64;
 
-        typedef HashMap<RefPtr<UString::Rep>, RefPtr<EvalNode> > EvalCacheMap;
+        typedef HashMap<RefPtr<UString::Rep>, RefPtr<EvalExecutable> > EvalCacheMap;
         EvalCacheMap m_cacheMap;
     };
 
         EvalCacheMap m_cacheMap;
     };
 
index eeeac6f4c3e3712d57f157f4c23aad78be286485..bcef7fb196a9c48b543315f3c0e6c0d4e78e0237 100644 (file)
@@ -53,7 +53,7 @@ namespace JSC {
     class StructureChain;
 
     // Structure used by op_get_by_id_self_list and op_get_by_id_proto_list instruction to hold data off the main opcode stream.
     class StructureChain;
 
     // Structure used by op_get_by_id_self_list and op_get_by_id_proto_list instruction to hold data off the main opcode stream.
-    struct PolymorphicAccessStructureList {
+    struct PolymorphicAccessStructureList : FastAllocBase {
         struct PolymorphicStubInfo {
             bool isChain;
             PolymorphicAccessStructureListStubRoutineType stubRoutine;
         struct PolymorphicStubInfo {
             bool isChain;
             PolymorphicAccessStructureListStubRoutineType stubRoutine;
index ec39f11cc25b535d8eb6b77bb7f4c70eb4aa3721..d9b2153dcad34154e67ca88c828ecf48418c0965 100644 (file)
@@ -113,6 +113,7 @@ namespace JSC {
         macro(op_put_by_id_generic, 8) \
         macro(op_del_by_id, 4) \
         macro(op_get_by_val, 4) \
         macro(op_put_by_id_generic, 8) \
         macro(op_del_by_id, 4) \
         macro(op_get_by_val, 4) \
+        macro(op_get_by_pname, 7) \
         macro(op_put_by_val, 4) \
         macro(op_del_by_val, 4) \
         macro(op_put_by_index, 4) \
         macro(op_put_by_val, 4) \
         macro(op_del_by_val, 4) \
         macro(op_put_by_index, 4) \
@@ -127,9 +128,11 @@ namespace JSC {
         macro(op_jneq_ptr, 4) \
         macro(op_jnless, 4) \
         macro(op_jnlesseq, 4) \
         macro(op_jneq_ptr, 4) \
         macro(op_jnless, 4) \
         macro(op_jnlesseq, 4) \
+        macro(op_jless, 4) \
         macro(op_jmp_scopes, 3) \
         macro(op_loop, 2) \
         macro(op_loop_if_true, 3) \
         macro(op_jmp_scopes, 3) \
         macro(op_loop, 2) \
         macro(op_loop_if_true, 3) \
+        macro(op_loop_if_false, 3) \
         macro(op_loop_if_less, 4) \
         macro(op_loop_if_lesseq, 4) \
         macro(op_switch_imm, 4) \
         macro(op_loop_if_less, 4) \
         macro(op_loop_if_lesseq, 4) \
         macro(op_switch_imm, 4) \
@@ -152,8 +155,8 @@ namespace JSC {
         macro(op_strcat, 4) \
         macro(op_to_primitive, 3) \
         \
         macro(op_strcat, 4) \
         macro(op_to_primitive, 3) \
         \
-        macro(op_get_pnames, 3) \
-        macro(op_next_pname, 4) \
+        macro(op_get_pnames, 6) \
+        macro(op_next_pname, 7) \
         \
         macro(op_push_scope, 2) \
         macro(op_pop_scope, 1) \
         \
         macro(op_push_scope, 2) \
         macro(op_pop_scope, 1) \
@@ -193,7 +196,11 @@ namespace JSC {
     #undef VERIFY_OPCODE_ID
 
 #if HAVE(COMPUTED_GOTO)
     #undef VERIFY_OPCODE_ID
 
 #if HAVE(COMPUTED_GOTO)
+#if COMPILER(RVCT)
+    typedef void* Opcode;
+#else
     typedef const void* Opcode;
     typedef const void* Opcode;
+#endif
 #else
     typedef OpcodeID Opcode;
 #endif
 #else
     typedef OpcodeID Opcode;
 #endif
index 86517233ae015f014499e4b7b05ce8974c32d664..3f0babc5491cc1d72cb3cf54679ffc3d1a163d8b 100644 (file)
@@ -33,7 +33,7 @@
 #include "Interpreter.h"
 #include "Opcode.h"
 
 #include "Interpreter.h"
 #include "Opcode.h"
 
-#if !PLATFORM(WIN_OS)
+#if !OS(WINDOWS)
 #include <unistd.h>
 #endif
 
 #include <unistd.h>
 #endif
 
@@ -91,7 +91,7 @@ void SamplingFlags::stop() {}
 uint32_t SamplingFlags::s_flags = 1 << 15;
 
 
 uint32_t SamplingFlags::s_flags = 1 << 15;
 
 
-#if PLATFORM(WIN_OS)
+#if OS(WINDOWS)
 
 static void sleepForMicroseconds(unsigned us)
 {
 
 static void sleepForMicroseconds(unsigned us)
 {
@@ -157,7 +157,7 @@ void SamplingThread::stop()
 }
 
 
 }
 
 
-void ScopeSampleRecord::sample(CodeBlock* codeBlock, Instruction* vPC)
+void ScriptSampleRecord::sample(CodeBlock* codeBlock, Instruction* vPC)
 {
     if (!m_samples) {
         m_size = codeBlock->instructions().size();
 {
     if (!m_samples) {
         m_size = codeBlock->instructions().size();
@@ -196,8 +196,8 @@ void SamplingTool::doRun()
 
 #if ENABLE(CODEBLOCK_SAMPLING)
     if (CodeBlock* codeBlock = sample.codeBlock()) {
 
 #if ENABLE(CODEBLOCK_SAMPLING)
     if (CodeBlock* codeBlock = sample.codeBlock()) {
-        MutexLocker locker(m_scopeSampleMapMutex);
-        ScopeSampleRecord* record = m_scopeSampleMap->get(codeBlock->ownerNode());
+        MutexLocker locker(m_scriptSampleMapMutex);
+        ScriptSampleRecord* record = m_scopeSampleMap->get(codeBlock->ownerExecutable());
         ASSERT(record);
         record->sample(codeBlock, sample.vPC());
     }
         ASSERT(record);
         record->sample(codeBlock, sample.vPC());
     }
@@ -209,13 +209,13 @@ void SamplingTool::sample()
     s_samplingTool->doRun();
 }
 
     s_samplingTool->doRun();
 }
 
-void SamplingTool::notifyOfScope(ScopeNode* scope)
+void SamplingTool::notifyOfScope(ScriptExecutable* script)
 {
 #if ENABLE(CODEBLOCK_SAMPLING)
 {
 #if ENABLE(CODEBLOCK_SAMPLING)
-    MutexLocker locker(m_scopeSampleMapMutex);
-    m_scopeSampleMap->set(scope, new ScopeSampleRecord(scope));
+    MutexLocker locker(m_scriptSampleMapMutex);
+    m_scopeSampleMap->set(script, new ScriptSampleRecord(script));
 #else
 #else
-    UNUSED_PARAM(scope);
+    UNUSED_PARAM(script);
 #endif
 }
 
 #endif
 }
 
@@ -254,10 +254,10 @@ static int compareLineCountInfoSampling(const void* left, const void* right)
     return (leftLineCount->line > rightLineCount->line) ? 1 : (leftLineCount->line < rightLineCount->line) ? -1 : 0;
 }
 
     return (leftLineCount->line > rightLineCount->line) ? 1 : (leftLineCount->line < rightLineCount->line) ? -1 : 0;
 }
 
-static int compareScopeSampleRecords(const void* left, const void* right)
+static int compareScriptSampleRecords(const void* left, const void* right)
 {
 {
-    const ScopeSampleRecord* const leftValue = *static_cast<const ScopeSampleRecord* const *>(left);
-    const ScopeSampleRecord* const rightValue = *static_cast<const ScopeSampleRecord* const *>(right);
+    const ScriptSampleRecord* const leftValue = *static_cast<const ScriptSampleRecord* const *>(left);
+    const ScriptSampleRecord* const rightValue = *static_cast<const ScriptSampleRecord* const *>(right);
 
     return (leftValue->m_sampleCount < rightValue->m_sampleCount) ? 1 : (leftValue->m_sampleCount > rightValue->m_sampleCount) ? -1 : 0;
 }
 
     return (leftValue->m_sampleCount < rightValue->m_sampleCount) ? 1 : (leftValue->m_sampleCount > rightValue->m_sampleCount) ? -1 : 0;
 }
@@ -318,26 +318,26 @@ void SamplingTool::dump(ExecState* exec)
     // (3) Build and sort 'codeBlockSamples' array.
 
     int scopeCount = m_scopeSampleMap->size();
     // (3) Build and sort 'codeBlockSamples' array.
 
     int scopeCount = m_scopeSampleMap->size();
-    Vector<ScopeSampleRecord*> codeBlockSamples(scopeCount);
-    ScopeSampleRecordMap::iterator iter = m_scopeSampleMap->begin();
+    Vector<ScriptSampleRecord*> codeBlockSamples(scopeCount);
+    ScriptSampleRecordMap::iterator iter = m_scopeSampleMap->begin();
     for (int i = 0; i < scopeCount; ++i, ++iter)
         codeBlockSamples[i] = iter->second;
 
     for (int i = 0; i < scopeCount; ++i, ++iter)
         codeBlockSamples[i] = iter->second;
 
-    qsort(codeBlockSamples.begin(), scopeCount, sizeof(ScopeSampleRecord*), compareScopeSampleRecords);
+    qsort(codeBlockSamples.begin(), scopeCount, sizeof(ScriptSampleRecord*), compareScriptSampleRecords);
 
     // (4) Print data from 'codeBlockSamples' array.
 
     printf("\nCodeBlock samples\n\n"); 
 
     for (int i = 0; i < scopeCount; ++i) {
 
     // (4) Print data from 'codeBlockSamples' array.
 
     printf("\nCodeBlock samples\n\n"); 
 
     for (int i = 0; i < scopeCount; ++i) {
-        ScopeSampleRecord* record = codeBlockSamples[i];
+        ScriptSampleRecord* record = codeBlockSamples[i];
         CodeBlock* codeBlock = record->m_codeBlock;
 
         double blockPercent = (record->m_sampleCount * 100.0) / m_sampleCount;
 
         if (blockPercent >= 1) {
             //Instruction* code = codeBlock->instructions().begin();
         CodeBlock* codeBlock = record->m_codeBlock;
 
         double blockPercent = (record->m_sampleCount * 100.0) / m_sampleCount;
 
         if (blockPercent >= 1) {
             //Instruction* code = codeBlock->instructions().begin();
-            printf("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_scope->sourceURL().UTF8String().c_str(), codeBlock->lineNumberForBytecodeOffset(exec, 0), record->m_sampleCount, m_sampleCount, blockPercent);
+            printf("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_executable->sourceURL().UTF8String().c_str(), codeBlock->lineNumberForBytecodeOffset(exec, 0), record->m_sampleCount, m_sampleCount, blockPercent);
             if (i < 10) {
                 HashMap<unsigned,unsigned> lineCounts;
                 codeBlock->dump(exec);
             if (i < 10) {
                 HashMap<unsigned,unsigned> lineCounts;
                 codeBlock->dump(exec);
index 7d7dc9c9593321c60689bed39418e4299bfa340c..8e3ed9e5e0e762bf4e0d65a6aa92f34ec950f2b5 100644 (file)
@@ -38,6 +38,8 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
+    class ScriptExecutable;
+
     class SamplingFlags {
         friend class JIT;
     public:
     class SamplingFlags {
         friend class JIT;
     public:
@@ -92,9 +94,9 @@ namespace JSC {
     class ScopeNode;
     struct Instruction;
 
     class ScopeNode;
     struct Instruction;
 
-    struct ScopeSampleRecord {
-        ScopeSampleRecord(ScopeNode* scope)
-            : m_scope(scope)
+    struct ScriptSampleRecord {
+        ScriptSampleRecord(ScriptExecutable* executable)
+            : m_executable(executable)
             , m_codeBlock(0)
             , m_sampleCount(0)
             , m_opcodeSampleCount(0)
             , m_codeBlock(0)
             , m_sampleCount(0)
             , m_opcodeSampleCount(0)
@@ -103,7 +105,7 @@ namespace JSC {
         {
         }
         
         {
         }
         
-        ~ScopeSampleRecord()
+        ~ScriptSampleRecord()
         {
             if (m_samples)
                 free(m_samples);
         {
             if (m_samples)
                 free(m_samples);
@@ -111,7 +113,7 @@ namespace JSC {
         
         void sample(CodeBlock*, Instruction*);
 
         
         void sample(CodeBlock*, Instruction*);
 
-        RefPtr<ScopeNode> m_scope;
+        RefPtr<ScriptExecutable> m_executable;
         CodeBlock* m_codeBlock;
         int m_sampleCount;
         int m_opcodeSampleCount;
         CodeBlock* m_codeBlock;
         int m_sampleCount;
         int m_opcodeSampleCount;
@@ -119,7 +121,7 @@ namespace JSC {
         unsigned m_size;
     };
 
         unsigned m_size;
     };
 
-    typedef WTF::HashMap<ScopeNode*, ScopeSampleRecord*> ScopeSampleRecordMap;
+    typedef WTF::HashMap<ScriptExecutable*, ScriptSampleRecord*> ScriptSampleRecordMap;
 
     class SamplingThread {
     public:
 
     class SamplingThread {
     public:
@@ -136,11 +138,11 @@ namespace JSC {
 
     class SamplingTool {
     public:
 
     class SamplingTool {
     public:
-        friend class CallRecord;
+        friend struct CallRecord;
         friend class HostCallRecord;
         
 #if ENABLE(OPCODE_SAMPLING)
         friend class HostCallRecord;
         
 #if ENABLE(OPCODE_SAMPLING)
-        class CallRecord : Noncopyable {
+        class CallRecord : public Noncopyable {
         public:
             CallRecord(SamplingTool* samplingTool)
                 : m_samplingTool(samplingTool)
         public:
             CallRecord(SamplingTool* samplingTool)
                 : m_samplingTool(samplingTool)
@@ -170,7 +172,7 @@ namespace JSC {
             }
         };
 #else
             }
         };
 #else
-        class CallRecord : Noncopyable {
+        class CallRecord : public Noncopyable {
         public:
             CallRecord(SamplingTool*)
             {
         public:
             CallRecord(SamplingTool*)
             {
@@ -193,7 +195,7 @@ namespace JSC {
             , m_sampleCount(0)
             , m_opcodeSampleCount(0)
 #if ENABLE(CODEBLOCK_SAMPLING)
             , m_sampleCount(0)
             , m_opcodeSampleCount(0)
 #if ENABLE(CODEBLOCK_SAMPLING)
-            , m_scopeSampleMap(new ScopeSampleRecordMap())
+            , m_scopeSampleMap(new ScriptSampleRecordMap())
 #endif
         {
             memset(m_opcodeSamples, 0, sizeof(m_opcodeSamples));
 #endif
         {
             memset(m_opcodeSamples, 0, sizeof(m_opcodeSamples));
@@ -210,7 +212,7 @@ namespace JSC {
         void setup();
         void dump(ExecState*);
 
         void setup();
         void dump(ExecState*);
 
-        void notifyOfScope(ScopeNode* scope);
+        void notifyOfScope(ScriptExecutable* scope);
 
         void sample(CodeBlock* codeBlock, Instruction* vPC)
         {
 
         void sample(CodeBlock* codeBlock, Instruction* vPC)
         {
@@ -266,8 +268,8 @@ namespace JSC {
         unsigned m_opcodeSamplesInCTIFunctions[numOpcodeIDs];
         
 #if ENABLE(CODEBLOCK_SAMPLING)
         unsigned m_opcodeSamplesInCTIFunctions[numOpcodeIDs];
         
 #if ENABLE(CODEBLOCK_SAMPLING)
-        Mutex m_scopeSampleMapMutex;
-        OwnPtr<ScopeSampleRecordMap> m_scopeSampleMap;
+        Mutex m_scriptSampleMapMutex;
+        OwnPtr<ScriptSampleRecordMap> m_scopeSampleMap;
 #endif
     };
 
 #endif
     };
 
index bf3fdc4659bcdbfc33930ced14bcab89b7185a68..018d83289bf087cff99d08c23f66ff3952842895 100644 (file)
@@ -31,44 +31,44 @@ namespace JSC {
 #if ENABLE(JIT)
 void StructureStubInfo::deref()
 {
 #if ENABLE(JIT)
 void StructureStubInfo::deref()
 {
-    switch (opcodeID) {
-    case op_get_by_id_self:
+    switch (accessType) {
+    case access_get_by_id_self:
         u.getByIdSelf.baseObjectStructure->deref();
         return;
         u.getByIdSelf.baseObjectStructure->deref();
         return;
-    case op_get_by_id_proto:
+    case access_get_by_id_proto:
         u.getByIdProto.baseObjectStructure->deref();
         u.getByIdProto.prototypeStructure->deref();
         return;
         u.getByIdProto.baseObjectStructure->deref();
         u.getByIdProto.prototypeStructure->deref();
         return;
-    case op_get_by_id_chain:
+    case access_get_by_id_chain:
         u.getByIdChain.baseObjectStructure->deref();
         u.getByIdChain.chain->deref();
         return;
         u.getByIdChain.baseObjectStructure->deref();
         u.getByIdChain.chain->deref();
         return;
-    case op_get_by_id_self_list: {
+    case access_get_by_id_self_list: {
         PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
         polymorphicStructures->derefStructures(u.getByIdSelfList.listSize);
         delete polymorphicStructures;
         return;
     }
         PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
         polymorphicStructures->derefStructures(u.getByIdSelfList.listSize);
         delete polymorphicStructures;
         return;
     }
-    case op_get_by_id_proto_list: {
+    case access_get_by_id_proto_list: {
         PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList;
         polymorphicStructures->derefStructures(u.getByIdProtoList.listSize);
         delete polymorphicStructures;
         return;
     }
         PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList;
         polymorphicStructures->derefStructures(u.getByIdProtoList.listSize);
         delete polymorphicStructures;
         return;
     }
-    case op_put_by_id_transition:
+    case access_put_by_id_transition:
         u.putByIdTransition.previousStructure->deref();
         u.putByIdTransition.structure->deref();
         u.putByIdTransition.chain->deref();
         return;
         u.putByIdTransition.previousStructure->deref();
         u.putByIdTransition.structure->deref();
         u.putByIdTransition.chain->deref();
         return;
-    case op_put_by_id_replace:
+    case access_put_by_id_replace:
         u.putByIdReplace.baseObjectStructure->deref();
         return;
         u.putByIdReplace.baseObjectStructure->deref();
         return;
-    case op_get_by_id:
-    case op_put_by_id:
-    case op_get_by_id_generic:
-    case op_put_by_id_generic:
-    case op_get_array_length:
-    case op_get_string_length:
+    case access_get_by_id:
+    case access_put_by_id:
+    case access_get_by_id_generic:
+    case access_put_by_id_generic:
+    case access_get_array_length:
+    case access_get_string_length:
         // These instructions don't ref their Structures.
         return;
     default:
         // These instructions don't ref their Structures.
         return;
     default:
index 95dd2664ab3cfd4761aa734ef6d3d7896433e077..8e2c489aa93023139b9af96dae8e565decf224fe 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
+    enum AccessType {
+        access_get_by_id_self,
+        access_get_by_id_proto,
+        access_get_by_id_chain,
+        access_get_by_id_self_list,
+        access_get_by_id_proto_list,
+        access_put_by_id_transition,
+        access_put_by_id_replace,
+        access_get_by_id,
+        access_put_by_id,
+        access_get_by_id_generic,
+        access_put_by_id_generic,
+        access_get_array_length,
+        access_get_string_length,
+    };
+
     struct StructureStubInfo {
     struct StructureStubInfo {
-        StructureStubInfo(OpcodeID opcodeID)
-            : opcodeID(opcodeID)
+        StructureStubInfo(AccessType accessType)
+            : accessType(accessType)
+            , seen(false)
         {
         }
 
         void initGetByIdSelf(Structure* baseObjectStructure)
         {
         {
         }
 
         void initGetByIdSelf(Structure* baseObjectStructure)
         {
-            opcodeID = op_get_by_id_self;
+            accessType = access_get_by_id_self;
 
             u.getByIdSelf.baseObjectStructure = baseObjectStructure;
             baseObjectStructure->ref();
 
             u.getByIdSelf.baseObjectStructure = baseObjectStructure;
             baseObjectStructure->ref();
@@ -51,7 +68,7 @@ namespace JSC {
 
         void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure)
         {
 
         void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure)
         {
-            opcodeID = op_get_by_id_proto;
+            accessType = access_get_by_id_proto;
 
             u.getByIdProto.baseObjectStructure = baseObjectStructure;
             baseObjectStructure->ref();
 
             u.getByIdProto.baseObjectStructure = baseObjectStructure;
             baseObjectStructure->ref();
@@ -62,7 +79,7 @@ namespace JSC {
 
         void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain)
         {
 
         void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain)
         {
-            opcodeID = op_get_by_id_chain;
+            accessType = access_get_by_id_chain;
 
             u.getByIdChain.baseObjectStructure = baseObjectStructure;
             baseObjectStructure->ref();
 
             u.getByIdChain.baseObjectStructure = baseObjectStructure;
             baseObjectStructure->ref();
@@ -73,7 +90,7 @@ namespace JSC {
 
         void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize)
         {
 
         void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize)
         {
-            opcodeID = op_get_by_id_self_list;
+            accessType = access_get_by_id_self_list;
 
             u.getByIdProtoList.structureList = structureList;
             u.getByIdProtoList.listSize = listSize;
 
             u.getByIdProtoList.structureList = structureList;
             u.getByIdProtoList.listSize = listSize;
@@ -81,7 +98,7 @@ namespace JSC {
 
         void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize)
         {
 
         void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize)
         {
-            opcodeID = op_get_by_id_proto_list;
+            accessType = access_get_by_id_proto_list;
 
             u.getByIdProtoList.structureList = structureList;
             u.getByIdProtoList.listSize = listSize;
 
             u.getByIdProtoList.structureList = structureList;
             u.getByIdProtoList.listSize = listSize;
@@ -91,7 +108,7 @@ namespace JSC {
 
         void initPutByIdTransition(Structure* previousStructure, Structure* structure, StructureChain* chain)
         {
 
         void initPutByIdTransition(Structure* previousStructure, Structure* structure, StructureChain* chain)
         {
-            opcodeID = op_put_by_id_transition;
+            accessType = access_put_by_id_transition;
 
             u.putByIdTransition.previousStructure = previousStructure;
             previousStructure->ref();
 
             u.putByIdTransition.previousStructure = previousStructure;
             previousStructure->ref();
@@ -105,7 +122,7 @@ namespace JSC {
 
         void initPutByIdReplace(Structure* baseObjectStructure)
         {
 
         void initPutByIdReplace(Structure* baseObjectStructure)
         {
-            opcodeID = op_put_by_id_replace;
+            accessType = access_put_by_id_replace;
     
             u.putByIdReplace.baseObjectStructure = baseObjectStructure;
             baseObjectStructure->ref();
     
             u.putByIdReplace.baseObjectStructure = baseObjectStructure;
             baseObjectStructure->ref();
@@ -113,7 +130,19 @@ namespace JSC {
 
         void deref();
 
 
         void deref();
 
-        OpcodeID opcodeID;
+        bool seenOnce()
+        {
+            return seen;
+        }
+
+        void setSeen()
+        {
+            seen = true;
+        }
+
+        int accessType : 31;
+        int seen : 1;
+
         union {
             struct {
                 Structure* baseObjectStructure;
         union {
             struct {
                 Structure* baseObjectStructure;
index 683372effc104d2a6f30bac720f91bcaa384a817..b0a0877c15ba83b47b4dff470e37e487c99f3d1d 100644 (file)
@@ -256,15 +256,15 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
         m_nextGlobalIndex -= symbolTable->size();
 
         for (size_t i = 0; i < functionStack.size(); ++i) {
         m_nextGlobalIndex -= symbolTable->size();
 
         for (size_t i = 0; i < functionStack.size(); ++i) {
-            FuncDeclNode* funcDecl = functionStack[i];
-            globalObject->removeDirect(funcDecl->m_ident); // Make sure our new function is not shadowed by an old property.
-            emitNewFunction(addGlobalVar(funcDecl->m_ident, false), funcDecl);
+            FunctionBodyNode* function = functionStack[i];
+            globalObject->removeDirect(function->ident()); // Make sure our new function is not shadowed by an old property.
+            emitNewFunction(addGlobalVar(function->ident(), false), function);
         }
 
         Vector<RegisterID*, 32> newVars;
         for (size_t i = 0; i < varStack.size(); ++i)
         }
 
         Vector<RegisterID*, 32> newVars;
         for (size_t i = 0; i < varStack.size(); ++i)
-            if (!globalObject->hasProperty(exec, varStack[i].first))
-                newVars.append(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
+            if (!globalObject->hasProperty(exec, *varStack[i].first))
+                newVars.append(addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
 
         preserveLastVar();
 
 
         preserveLastVar();
 
@@ -272,16 +272,16 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
             emitLoad(newVars[i], jsUndefined());
     } else {
         for (size_t i = 0; i < functionStack.size(); ++i) {
             emitLoad(newVars[i], jsUndefined());
     } else {
         for (size_t i = 0; i < functionStack.size(); ++i) {
-            FuncDeclNode* funcDecl = functionStack[i];
-            globalObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec, scopeChain.node()), DontDelete);
+            FunctionBodyNode* function = functionStack[i];
+            globalObject->putWithAttributes(exec, function->ident(), new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain.node()), DontDelete);
         }
         for (size_t i = 0; i < varStack.size(); ++i) {
         }
         for (size_t i = 0; i < varStack.size(); ++i) {
-            if (globalObject->hasProperty(exec, varStack[i].first))
+            if (globalObject->hasProperty(exec, *varStack[i].first))
                 continue;
             int attributes = DontDelete;
             if (varStack[i].second & DeclarationStacks::IsConstant)
                 attributes |= ReadOnly;
                 continue;
             int attributes = DontDelete;
             if (varStack[i].second & DeclarationStacks::IsConstant)
                 attributes |= ReadOnly;
-            globalObject->putWithAttributes(exec, varStack[i].first, jsUndefined(), attributes);
+            globalObject->putWithAttributes(exec, *varStack[i].first, jsUndefined(), attributes);
         }
 
         preserveLastVar();
         }
 
         preserveLastVar();
@@ -339,18 +339,18 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
 
     const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
     for (size_t i = 0; i < functionStack.size(); ++i) {
 
     const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
     for (size_t i = 0; i < functionStack.size(); ++i) {
-        FuncDeclNode* funcDecl = functionStack[i];
-        const Identifier& ident = funcDecl->m_ident;
+        FunctionBodyNode* function = functionStack[i];
+        const Identifier& ident = function->ident();
         m_functions.add(ident.ustring().rep());
         m_functions.add(ident.ustring().rep());
-        emitNewFunction(addVar(ident, false), funcDecl);
+        emitNewFunction(addVar(ident, false), function);
     }
 
     const DeclarationStacks::VarStack& varStack = functionBody->varStack();
     for (size_t i = 0; i < varStack.size(); ++i)
     }
 
     const DeclarationStacks::VarStack& varStack = functionBody->varStack();
     for (size_t i = 0; i < varStack.size(); ++i)
-        addVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
+        addVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
 
 
-    const Identifier* parameters = functionBody->parameters();
-    size_t parameterCount = functionBody->parameterCount();
+    FunctionParameters& parameters = *functionBody->parameters();
+    size_t parameterCount = parameters.size();
     m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
     m_parameters.grow(1 + parameterCount); // reserve space for "this"
 
     m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
     m_parameters.grow(1 + parameterCount); // reserve space for "this"
 
@@ -397,6 +397,18 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge
     codeBlock->setGlobalData(m_globalData);
     m_codeBlock->m_numParameters = 1; // Allocate space for "this"
 
     codeBlock->setGlobalData(m_globalData);
     m_codeBlock->m_numParameters = 1; // Allocate space for "this"
 
+    const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
+    for (size_t i = 0; i < functionStack.size(); ++i)
+        m_codeBlock->addFunctionDecl(makeFunction(m_globalData, functionStack[i]));
+
+    const DeclarationStacks::VarStack& varStack = evalNode->varStack();
+    unsigned numVariables = varStack.size();
+    Vector<Identifier> variables;
+    variables.reserveCapacity(numVariables);
+    for (size_t i = 0; i < numVariables; ++i)
+        variables.append(*varStack[i].first);
+    codeBlock->adoptVariables(variables);
+
     preserveLastVar();
 }
 
     preserveLastVar();
 }
 
@@ -470,7 +482,8 @@ RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
         return 0;
 
     SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
         return 0;
 
     SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
-    ASSERT(!entry.isNull());
+    if (entry.isNull())
+        return 0;
 
     return &registerFor(entry.getIndex());
 }
 
     return &registerFor(entry.getIndex());
 }
@@ -521,7 +534,7 @@ PassRefPtr<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, c
         m_labelScopes.removeLast();
 
     // Allocate new label scope.
         m_labelScopes.removeLast();
 
     // Allocate new label scope.
-    LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : 0); // Only loops have continue targets.
+    LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets.
     m_labelScopes.append(scope);
     return &m_labelScopes.last();
 }
     m_labelScopes.append(scope);
     return &m_labelScopes.last();
 }
@@ -595,14 +608,15 @@ void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
 
 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
 {
 
 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
 {
+    size_t begin = instructions().size();
     emitOpcode(target->isForward() ? op_jmp : op_loop);
     emitOpcode(target->isForward() ? op_jmp : op_loop);
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
 {
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
 {
-    if (m_lastOpcodeID == op_less && !target->isForward()) {
+    if (m_lastOpcodeID == op_less) {
         int dstIndex;
         int src1Index;
         int src2Index;
         int dstIndex;
         int src1Index;
         int src2Index;
@@ -611,10 +625,12 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
-            emitOpcode(op_loop_if_less);
+
+            size_t begin = instructions().size();
+            emitOpcode(target->isForward() ? op_jless : op_loop_if_less);
             instructions().append(src1Index);
             instructions().append(src2Index);
             instructions().append(src1Index);
             instructions().append(src2Index);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) {
             return target;
         }
     } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) {
@@ -626,10 +642,12 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_loop_if_lesseq);
             instructions().append(src1Index);
             instructions().append(src2Index);
             emitOpcode(op_loop_if_lesseq);
             instructions().append(src1Index);
             instructions().append(src2Index);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
             return target;
         }
     } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
@@ -640,9 +658,11 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jeq_null);
             instructions().append(srcIndex);
             emitOpcode(op_jeq_null);
             instructions().append(srcIndex);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
             return target;
         }
     } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
@@ -653,24 +673,26 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jneq_null);
             instructions().append(srcIndex);
             emitOpcode(op_jneq_null);
             instructions().append(srcIndex);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     }
 
             return target;
         }
     }
 
+    size_t begin = instructions().size();
+
     emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
     instructions().append(cond->index());
     emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
     instructions().append(cond->index());
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
 {
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
 {
-    ASSERT(target->isForward());
-
-    if (m_lastOpcodeID == op_less) {
+    if (m_lastOpcodeID == op_less && target->isForward()) {
         int dstIndex;
         int src1Index;
         int src2Index;
         int dstIndex;
         int src1Index;
         int src2Index;
@@ -679,13 +701,15 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jnless);
             instructions().append(src1Index);
             instructions().append(src2Index);
             emitOpcode(op_jnless);
             instructions().append(src1Index);
             instructions().append(src2Index);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
             return target;
         }
-    } else if (m_lastOpcodeID == op_lesseq) {
+    } else if (m_lastOpcodeID == op_lesseq && target->isForward()) {
         int dstIndex;
         int src1Index;
         int src2Index;
         int dstIndex;
         int src1Index;
         int src2Index;
@@ -694,10 +718,12 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jnlesseq);
             instructions().append(src1Index);
             instructions().append(src2Index);
             emitOpcode(op_jnlesseq);
             instructions().append(src1Index);
             instructions().append(src2Index);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     } else if (m_lastOpcodeID == op_not) {
             return target;
         }
     } else if (m_lastOpcodeID == op_not) {
@@ -708,12 +734,14 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
-            emitOpcode(op_jtrue);
+
+            size_t begin = instructions().size();
+            emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
             instructions().append(srcIndex);
             instructions().append(srcIndex);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
             return target;
         }
-    } else if (m_lastOpcodeID == op_eq_null) {
+    } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
         int dstIndex;
         int srcIndex;
 
         int dstIndex;
         int srcIndex;
 
@@ -721,12 +749,14 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jneq_null);
             instructions().append(srcIndex);
             emitOpcode(op_jneq_null);
             instructions().append(srcIndex);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
             return target;
         }
-    } else if (m_lastOpcodeID == op_neq_null) {
+    } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
         int dstIndex;
         int srcIndex;
 
         int dstIndex;
         int srcIndex;
 
@@ -734,49 +764,44 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jeq_null);
             instructions().append(srcIndex);
             emitOpcode(op_jeq_null);
             instructions().append(srcIndex);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     }
 
             return target;
         }
     }
 
-    emitOpcode(op_jfalse);
+    size_t begin = instructions().size();
+    emitOpcode(target->isForward() ? op_jfalse : op_loop_if_false);
     instructions().append(cond->index());
     instructions().append(cond->index());
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target)
 {
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target)
 {
+    size_t begin = instructions().size();
+
     emitOpcode(op_jneq_ptr);
     instructions().append(cond->index());
     instructions().append(m_scopeChain->globalObject()->d()->callFunction);
     emitOpcode(op_jneq_ptr);
     instructions().append(cond->index());
     instructions().append(m_scopeChain->globalObject()->d()->callFunction);
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target)
 {
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target)
 {
+    size_t begin = instructions().size();
+
     emitOpcode(op_jneq_ptr);
     instructions().append(cond->index());
     instructions().append(m_scopeChain->globalObject()->d()->applyFunction);
     emitOpcode(op_jneq_ptr);
     instructions().append(cond->index());
     instructions().append(m_scopeChain->globalObject()->d()->applyFunction);
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
     return target;
 }
 
-unsigned BytecodeGenerator::addConstant(FuncDeclNode* n)
-{
-    // No need to explicitly unique function body nodes -- they're unique already.
-    return m_codeBlock->addFunction(n);
-}
-
-unsigned BytecodeGenerator::addConstant(FuncExprNode* n)
-{
-    // No need to explicitly unique function expression nodes -- they're unique already.
-    return m_codeBlock->addFunctionExpression(n);
-}
-
 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
 {
     UString::Rep* rep = ident.ustring().rep();
 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
 {
     UString::Rep* rep = ident.ustring().rep();
@@ -879,7 +904,7 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst
             && src1->isTemporary()
             && m_codeBlock->isConstantRegisterIndex(src2->index())
             && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) {
             && src1->isTemporary()
             && m_codeBlock->isConstantRegisterIndex(src2->index())
             && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) {
-            const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->value();
+            const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->tryGetValue();
             if (value == "undefined") {
                 rewindUnaryOp();
                 emitOpcode(op_is_undefined);
             if (value == "undefined") {
                 rewindUnaryOp();
                 emitOpcode(op_is_undefined);
@@ -1190,7 +1215,7 @@ void BytecodeGenerator::emitMethodCheck()
 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
 {
 #if ENABLE(JIT)
 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
 {
 #if ENABLE(JIT)
-    m_codeBlock->addStructureStubInfo(StructureStubInfo(op_get_by_id));
+    m_codeBlock->addStructureStubInfo(StructureStubInfo(access_get_by_id));
 #else
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
 #else
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
@@ -1209,7 +1234,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
 #if ENABLE(JIT)
 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
 #if ENABLE(JIT)
-    m_codeBlock->addStructureStubInfo(StructureStubInfo(op_put_by_id));
+    m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
 #else
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
 #else
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
@@ -1254,6 +1279,19 @@ RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base,
 
 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
 
 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
+    for (size_t i = m_forInContextStack.size(); i > 0; i--) {
+        ForInContext& context = m_forInContextStack[i - 1];
+        if (context.propertyRegister == property) {
+            emitOpcode(op_get_by_pname);
+            instructions().append(dst->index());
+            instructions().append(base->index());
+            instructions().append(property->index());
+            instructions().append(context.expectedSubscriptRegister->index());
+            instructions().append(context.iterRegister->index());
+            instructions().append(context.indexRegister->index());
+            return dst;
+        }
+    }
     emitOpcode(op_get_by_val);
     instructions().append(dst->index());
     instructions().append(base->index());
     emitOpcode(op_get_by_val);
     instructions().append(dst->index());
     instructions().append(base->index());
@@ -1313,11 +1351,13 @@ RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elemen
     return dst;
 }
 
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FuncDeclNode* n)
+RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function)
 {
 {
+    unsigned index = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function));
+
     emitOpcode(op_new_func);
     instructions().append(dst->index());
     emitOpcode(op_new_func);
     instructions().append(dst->index());
-    instructions().append(addConstant(n));
+    instructions().append(index);
     return dst;
 }
 
     return dst;
 }
 
@@ -1332,9 +1372,12 @@ RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
 
 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
 {
 
 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
 {
+    FunctionBodyNode* function = n->body();
+    unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function));
+
     emitOpcode(op_new_func_exp);
     instructions().append(r0->index());
     emitOpcode(op_new_func_exp);
     instructions().append(r0->index());
-    instructions().append(addConstant(n));
+    instructions().append(index);
     return r0;
 }
 
     return r0;
 }
 
@@ -1712,6 +1755,8 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro
         }
 
         if (nNormalScopes) {
         }
 
         if (nNormalScopes) {
+            size_t begin = instructions().size();
+
             // We need to remove a number of dynamic scopes to get to the next
             // finally block
             emitOpcode(op_jmp_scopes);
             // We need to remove a number of dynamic scopes to get to the next
             // finally block
             emitOpcode(op_jmp_scopes);
@@ -1720,14 +1765,14 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro
             // If topScope == bottomScope then there isn't actually a finally block
             // left to emit, so make the jmp_scopes jump directly to the target label
             if (topScope == bottomScope) {
             // If topScope == bottomScope then there isn't actually a finally block
             // left to emit, so make the jmp_scopes jump directly to the target label
             if (topScope == bottomScope) {
-                instructions().append(target->offsetFrom(instructions().size()));
+                instructions().append(target->bind(begin, instructions().size()));
                 return target;
             }
 
             // Otherwise we just use jmp_scopes to pop a group of scopes and go
             // to the next instruction
             RefPtr<Label> nextInsn = newLabel();
                 return target;
             }
 
             // Otherwise we just use jmp_scopes to pop a group of scopes and go
             // to the next instruction
             RefPtr<Label> nextInsn = newLabel();
-            instructions().append(nextInsn->offsetFrom(instructions().size()));
+            instructions().append(nextInsn->bind(begin, instructions().size()));
             emitLabel(nextInsn.get());
         }
 
             emitLabel(nextInsn.get());
         }
 
@@ -1752,27 +1797,47 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetSco
     if (m_finallyDepth)
         return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
 
     if (m_finallyDepth)
         return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
 
+    size_t begin = instructions().size();
+
     emitOpcode(op_jmp_scopes);
     instructions().append(scopeDelta);
     emitOpcode(op_jmp_scopes);
     instructions().append(scopeDelta);
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
     return target;
 }
 
-RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target)
+RegisterID* BytecodeGenerator::emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget)
 {
 {
+    size_t begin = instructions().size();
+
+    emitOpcode(op_get_pnames);
+    instructions().append(dst->index());
+    instructions().append(base->index());
+    instructions().append(i->index());
+    instructions().append(size->index());
+    instructions().append(breakTarget->bind(begin, instructions().size()));
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target)
+{
+    size_t begin = instructions().size();
+
     emitOpcode(op_next_pname);
     instructions().append(dst->index());
     emitOpcode(op_next_pname);
     instructions().append(dst->index());
+    instructions().append(base->index());
+    instructions().append(i->index());
+    instructions().append(size->index());
     instructions().append(iter->index());
     instructions().append(iter->index());
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return dst;
 }
 
 RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
 {
 #if ENABLE(JIT)
     return dst;
 }
 
 RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
 {
 #if ENABLE(JIT)
-    HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
+    HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
 #else
 #else
-    HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
+    HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
 #endif
 
     m_codeBlock->addExceptionHandler(info);
 #endif
 
     m_codeBlock->addExceptionHandler(info);
@@ -1792,9 +1857,11 @@ RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSV
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
 {
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
 {
+    size_t begin = instructions().size();
+
     emitOpcode(op_jsr);
     instructions().append(retAddrDst->index());
     emitOpcode(op_jsr);
     instructions().append(retAddrDst->index());
-    instructions().append(finally->offsetFrom(instructions().size()));
+    instructions().append(finally->bind(begin, instructions().size()));
     emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it.
     return finally;
 }
     emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it.
     return finally;
 }
@@ -1805,7 +1872,7 @@ void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
     instructions().append(retAddrSrc->index());
 }
 
     instructions().append(retAddrSrc->index());
 }
 
-void BytecodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value)
+void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value)
 {
     ControlFlowContext context;
     context.isFinallyBlock = false;
 {
     ControlFlowContext context;
     context.isFinallyBlock = false;
@@ -1864,7 +1931,7 @@ static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32
         // We're emitting this after the clause labels should have been fixed, so 
         // the labels should not be "forward" references
         ASSERT(!labels[i]->isForward());
         // We're emitting this after the clause labels should have been fixed, so 
         // the labels should not be "forward" references
         ASSERT(!labels[i]->isForward());
-        jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); 
+        jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3)); 
     }
 }
 
     }
 }
 
@@ -1890,7 +1957,7 @@ static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32
         // We're emitting this after the clause labels should have been fixed, so 
         // the labels should not be "forward" references
         ASSERT(!labels[i]->isForward());
         // We're emitting this after the clause labels should have been fixed, so 
         // the labels should not be "forward" references
         ASSERT(!labels[i]->isForward());
-        jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); 
+        jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3)); 
     }
 }
 
     }
 }
 
@@ -1904,7 +1971,7 @@ static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t
         ASSERT(nodes[i]->isString());
         UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();
         OffsetLocation location;
         ASSERT(nodes[i]->isString());
         UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();
         OffsetLocation location;
-        location.branchOffset = labels[i]->offsetFrom(switchAddress);
+        location.branchOffset = labels[i]->bind(switchAddress, switchAddress + 3);
         jumpTable.offsetTable.add(clause, location);
     }
 }
         jumpTable.offsetTable.add(clause, location);
     }
 }
@@ -1915,23 +1982,23 @@ void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, E
     m_switchContextStack.removeLast();
     if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables();
     m_switchContextStack.removeLast();
     if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables();
-        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
+        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
 
         SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable();
 
         SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable();
-        prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max);
+        prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max);
     } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables();
     } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables();
-        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
+        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
         
         SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable();
         
         SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable();
-        prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max);
+        prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max);
     } else {
         ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
     } else {
         ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
-        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
+        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
 
         StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
 
         StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
-        prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes);
+        prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes);
     }
 }
 
     }
 }
 
index c273597eac58a0438c1cc0aeaaa5bd6bea7b6d72..8b6a425194a3103dcbe81786d0efdc44b2273d2c 100644 (file)
@@ -61,7 +61,14 @@ namespace JSC {
         FinallyContext finallyContext;
     };
 
         FinallyContext finallyContext;
     };
 
-    class BytecodeGenerator : public WTF::FastAllocBase {
+    struct ForInContext {
+        RefPtr<RegisterID> expectedSubscriptRegister;
+        RefPtr<RegisterID> iterRegister;
+        RefPtr<RegisterID> indexRegister;
+        RefPtr<RegisterID> propertyRegister;
+    };
+
+    class BytecodeGenerator : public FastAllocBase {
     public:
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
     public:
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
@@ -185,6 +192,19 @@ namespace JSC {
             return emitNode(0, n);
         }
 
             return emitNode(0, n);
         }
 
+        void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
+        {
+            if (!m_codeBlock->numberOfLineInfos() || m_codeBlock->lastLineInfo().lineNumber != n->lineNo()) {
+                LineInfo info = { instructions().size(), n->lineNo() };
+                m_codeBlock->addLineInfo(info);
+            }
+            if (m_emitNodeDepth >= s_maxEmitNodeDepth)
+                emitThrowExpressionTooDeepException();
+            ++m_emitNodeDepth;
+            n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue);
+            --m_emitNodeDepth;
+        }
+
         void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
         { 
             divot -= m_codeBlock->sourceOffset();
         void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
         { 
             divot -= m_codeBlock->sourceOffset();
@@ -254,7 +274,7 @@ namespace JSC {
         RegisterID* emitNewObject(RegisterID* dst);
         RegisterID* emitNewArray(RegisterID* dst, ElementNode*); // stops at first elision
 
         RegisterID* emitNewObject(RegisterID* dst);
         RegisterID* emitNewArray(RegisterID* dst, ElementNode*); // stops at first elision
 
-        RegisterID* emitNewFunction(RegisterID* dst, FuncDeclNode* func);
+        RegisterID* emitNewFunction(RegisterID* dst, FunctionBodyNode* body);
         RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
         RegisterID* emitNewRegExp(RegisterID* dst, RegExp* regExp);
 
         RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
         RegisterID* emitNewRegExp(RegisterID* dst, RegExp* regExp);
 
@@ -312,13 +332,13 @@ namespace JSC {
         PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*);
         void emitSubroutineReturn(RegisterID* retAddrSrc);
 
         PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*);
         void emitSubroutineReturn(RegisterID* retAddrSrc);
 
-        RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base) { return emitUnaryOp(op_get_pnames, dst, base); }
-        RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target);
+        RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
+        RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
 
         RegisterID* emitCatch(RegisterID*, Label* start, Label* end);
         void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); }
         RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValue message);
 
         RegisterID* emitCatch(RegisterID*, Label* start, Label* end);
         void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); }
         RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValue message);
-        void emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value);
+        void emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value);
 
         RegisterID* emitPushScope(RegisterID* scope);
         void emitPopScope();
 
         RegisterID* emitPushScope(RegisterID* scope);
         void emitPopScope();
@@ -331,6 +351,17 @@ namespace JSC {
         void pushFinallyContext(Label* target, RegisterID* returnAddrDst);
         void popFinallyContext();
 
         void pushFinallyContext(Label* target, RegisterID* returnAddrDst);
         void popFinallyContext();
 
+        void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
+        {
+            ForInContext context = { expectedBase, iter, index, propertyRegister };
+            m_forInContextStack.append(context);
+        }
+
+        void popOptimisedForIn()
+        {
+            m_forInContextStack.removeLast();
+        }
+
         LabelScope* breakTarget(const Identifier&);
         LabelScope* continueTarget(const Identifier&);
 
         LabelScope* breakTarget(const Identifier&);
         LabelScope* continueTarget(const Identifier&);
 
@@ -413,12 +444,20 @@ namespace JSC {
             return m_globals[-index - 1];
         }
 
             return m_globals[-index - 1];
         }
 
-        unsigned addConstant(FuncDeclNode*);
-        unsigned addConstant(FuncExprNode*);
         unsigned addConstant(const Identifier&);
         RegisterID* addConstantValue(JSValue);
         unsigned addRegExp(RegExp*);
 
         unsigned addConstant(const Identifier&);
         RegisterID* addConstantValue(JSValue);
         unsigned addRegExp(RegExp*);
 
+        PassRefPtr<FunctionExecutable> makeFunction(ExecState* exec, FunctionBodyNode* body)
+        {
+            return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
+        }
+
+        PassRefPtr<FunctionExecutable> makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
+        {
+            return FunctionExecutable::create(globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
+        }
+
         Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
         SymbolTable& symbolTable() { return *m_symbolTable; }
 
         Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
         SymbolTable& symbolTable() { return *m_symbolTable; }
 
@@ -445,12 +484,12 @@ namespace JSC {
         RegisterID m_thisRegister;
         RegisterID m_argumentsRegister;
         int m_activationRegisterIndex;
         RegisterID m_thisRegister;
         RegisterID m_argumentsRegister;
         int m_activationRegisterIndex;
-        WTF::SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
-        WTF::SegmentedVector<RegisterID, 32> m_calleeRegisters;
-        WTF::SegmentedVector<RegisterID, 32> m_parameters;
-        WTF::SegmentedVector<RegisterID, 32> m_globals;
-        WTF::SegmentedVector<Label, 32> m_labels;
-        WTF::SegmentedVector<LabelScope, 8> m_labelScopes;
+        SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
+        SegmentedVector<RegisterID, 32> m_calleeRegisters;
+        SegmentedVector<RegisterID, 32> m_parameters;
+        SegmentedVector<RegisterID, 32> m_globals;
+        SegmentedVector<Label, 32> m_labels;
+        SegmentedVector<LabelScope, 8> m_labelScopes;
         RefPtr<RegisterID> m_lastVar;
         int m_finallyDepth;
         int m_dynamicScopeDepth;
         RefPtr<RegisterID> m_lastVar;
         int m_finallyDepth;
         int m_dynamicScopeDepth;
@@ -459,6 +498,7 @@ namespace JSC {
 
         Vector<ControlFlowContext> m_scopeContextStack;
         Vector<SwitchInfo> m_switchContextStack;
 
         Vector<ControlFlowContext> m_scopeContextStack;
         Vector<SwitchInfo> m_switchContextStack;
+        Vector<ForInContext> m_forInContextStack;
 
         int m_nextGlobalIndex;
         int m_nextParameterIndex;
 
         int m_nextGlobalIndex;
         int m_nextParameterIndex;
index 0b3d0382423c9b5a6156b44a150304e346e26cdc..8cab1dbc00dc9ec623b37a20a86c484cc7122f88 100644 (file)
@@ -51,19 +51,17 @@ namespace JSC {
             m_location = location;
 
             unsigned size = m_unresolvedJumps.size();
             m_location = location;
 
             unsigned size = m_unresolvedJumps.size();
-            for (unsigned i = 0; i < size; ++i) {
-                unsigned j = m_unresolvedJumps[i];
-                m_codeBlock->instructions()[j].u.operand = m_location - j;
-            }
+            for (unsigned i = 0; i < size; ++i)
+                m_codeBlock->instructions()[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
         }
 
         }
 
-        int offsetFrom(int location) const
+        int bind(int opcode, int offset) const
         {
             if (m_location == invalidLocation) {
         {
             if (m_location == invalidLocation) {
-                m_unresolvedJumps.append(location);
+                m_unresolvedJumps.append(std::make_pair(opcode, offset));
                 return 0;
             }
                 return 0;
             }
-            return m_location - location;
+            return m_location - opcode;
         }
 
         void ref() { ++m_refCount; }
         }
 
         void ref() { ++m_refCount; }
@@ -77,7 +75,7 @@ namespace JSC {
         bool isForward() const { return m_location == invalidLocation; }
 
     private:
         bool isForward() const { return m_location == invalidLocation; }
 
     private:
-        typedef Vector<int, 8> JumpVector;
+        typedef Vector<std::pair<int, int>, 8> JumpVector;
 
         static const unsigned invalidLocation = UINT_MAX;
 
 
         static const unsigned invalidLocation = UINT_MAX;
 
diff --git a/bytecompiler/NodesCodegen.cpp b/bytecompiler/NodesCodegen.cpp
new file mode 100644 (file)
index 0000000..b66c50d
--- /dev/null
@@ -0,0 +1,1999 @@
+/*
+*  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+*  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+*  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+*  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+*  Copyright (C) 2007 Maks Orlovich
+*  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 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 "Nodes.h"
+#include "NodeConstructors.h"
+
+#include "BytecodeGenerator.h"
+#include "CallFrame.h"
+#include "Debugger.h"
+#include "JIT.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "JSStaticScopeObject.h"
+#include "LabelScope.h"
+#include "Lexer.h"
+#include "Operations.h"
+#include "Parser.h"
+#include "PropertyNameArray.h"
+#include "RegExpObject.h"
+#include "SamplingTool.h"
+#include <wtf/Assertions.h>
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/Threading.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+/*
+    Details of the emitBytecode function.
+
+    Return value: The register holding the production's value.
+             dst: An optional parameter specifying the most efficient destination at
+                  which to store the production's value. The callee must honor dst.
+
+    The dst argument provides for a crude form of copy propagation. For example,
+
+        x = 1
+
+    becomes
+    
+        load r[x], 1
+    
+    instead of 
+
+        load r0, 1
+        mov r[x], r0
+    
+    because the assignment node, "x =", passes r[x] as dst to the number node, "1".
+*/
+
+// ------------------------------ ThrowableExpressionData --------------------------------
+
+static void substitute(UString& string, const UString& substring)
+{
+    int position = string.find("%s");
+    ASSERT(position != -1);
+    string = makeString(string.substr(0, position), substring, string.substr(position + 2));
+}
+
+RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* message)
+{
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
+    generator.emitThrow(exception);
+    return exception;
+}
+
+RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const UString& label)
+{
+    UString message = messageTemplate;
+    substitute(message, label);
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
+    generator.emitThrow(exception);
+    return exception;
+}
+
+inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const Identifier& label)
+{
+    return emitThrowError(generator, type, messageTemplate, label.ustring());
+}
+
+// ------------------------------ NullNode -------------------------------------
+
+RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult())
+        return 0;
+    return generator.emitLoad(dst, jsNull());
+}
+
+// ------------------------------ BooleanNode ----------------------------------
+
+RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult())
+        return 0;
+    return generator.emitLoad(dst, m_value);
+}
+
+// ------------------------------ NumberNode -----------------------------------
+
+RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult())
+        return 0;
+    return generator.emitLoad(dst, m_value);
+}
+
+// ------------------------------ StringNode -----------------------------------
+
+RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult())
+        return 0;
+    return generator.emitLoad(dst, m_value);
+}
+
+// ------------------------------ RegExpNode -----------------------------------
+
+RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring());
+    if (!regExp->isValid())
+        return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", regExp->errorMessage());
+    if (dst == generator.ignoredResult())
+        return 0;
+    return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
+}
+
+// ------------------------------ ThisNode -------------------------------------
+
+RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult())
+        return 0;
+    return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
+}
+
+// ------------------------------ ResolveNode ----------------------------------
+
+bool ResolveNode::isPure(BytecodeGenerator& generator) const
+{
+    return generator.isLocal(m_ident);
+}
+
+RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (RegisterID* local = generator.registerFor(m_ident)) {
+        if (dst == generator.ignoredResult())
+            return 0;
+        return generator.moveToDestinationIfNeeded(dst, local);
+    }
+    
+    generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
+    return generator.emitResolve(generator.finalDestination(dst), m_ident);
+}
+
+// ------------------------------ ArrayNode ------------------------------------
+
+RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    // FIXME: Should we put all of this code into emitNewArray?
+
+    unsigned length = 0;
+    ElementNode* firstPutElement;
+    for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
+        if (firstPutElement->elision())
+            break;
+        ++length;
+    }
+
+    if (!firstPutElement && !m_elision)
+        return generator.emitNewArray(generator.finalDestination(dst), m_element);
+
+    RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element);
+
+    for (ElementNode* n = firstPutElement; n; n = n->next()) {
+        RegisterID* value = generator.emitNode(n->value());
+        length += n->elision();
+        generator.emitPutByIndex(array.get(), length++, value);
+    }
+
+    if (m_elision) {
+        RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length));
+        generator.emitPutById(array.get(), generator.propertyNames().length, value);
+    }
+
+    return generator.moveToDestinationIfNeeded(dst, array.get());
+}
+
+bool ArrayNode::isSimpleArray() const
+{
+    if (m_elision || m_optional)
+        return false;
+    for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
+        if (ptr->elision())
+            return false;
+    }
+    return true;
+}
+
+ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const
+{
+    ASSERT(!m_elision && !m_optional);
+    ElementNode* ptr = m_element;
+    if (!ptr)
+        return 0;
+    ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value());
+    ArgumentListNode* tail = head;
+    ptr = ptr->next();
+    for (; ptr; ptr = ptr->next()) {
+        ASSERT(!ptr->elision());
+        tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value());
+    }
+    return head;
+}
+
+// ------------------------------ ObjectLiteralNode ----------------------------
+
+RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+     if (!m_list) {
+         if (dst == generator.ignoredResult())
+             return 0;
+         return generator.emitNewObject(generator.finalDestination(dst));
+     }
+     return generator.emitNode(dst, m_list);
+}
+
+// ------------------------------ PropertyListNode -----------------------------
+
+RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> newObj = generator.tempDestination(dst);
+    
+    generator.emitNewObject(newObj.get());
+    
+    for (PropertyListNode* p = this; p; p = p->m_next) {
+        RegisterID* value = generator.emitNode(p->m_node->m_assign);
+        
+        switch (p->m_node->m_type) {
+            case PropertyNode::Constant: {
+                generator.emitPutById(newObj.get(), p->m_node->name(), value);
+                break;
+            }
+            case PropertyNode::Getter: {
+                generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
+                break;
+            }
+            case PropertyNode::Setter: {
+                generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
+                break;
+            }
+            default:
+                ASSERT_NOT_REACHED();
+        }
+    }
+    
+    return generator.moveToDestinationIfNeeded(dst, newObj.get());
+}
+
+// ------------------------------ BracketAccessorNode --------------------------------
+
+RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
+    RegisterID* property = generator.emitNode(m_subscript);
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
+}
+
+// ------------------------------ DotAccessorNode --------------------------------
+
+RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RegisterID* base = generator.emitNode(m_base);
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
+}
+
+// ------------------------------ ArgumentListNode -----------------------------
+
+RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    ASSERT(m_expr);
+    return generator.emitNode(dst, m_expr);
+}
+
+// ------------------------------ NewExprNode ----------------------------------
+
+RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> func = generator.emitNode(m_expr);
+    return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ EvalFunctionCallNode ----------------------------------
+
+RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> func = generator.tempDestination(dst);
+    RefPtr<RegisterID> thisRegister = generator.newTemporary();
+    generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
+    generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval);
+    return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallValueNode ----------------------------------
+
+RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> func = generator.emitNode(m_expr);
+    RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
+    return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallResolveNode ----------------------------------
+
+RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
+        RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
+        return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+    }
+
+    int index = 0;
+    size_t depth = 0;
+    JSObject* globalObject = 0;
+    if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
+        RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
+        RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
+        return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+    }
+
+    RefPtr<RegisterID> func = generator.newTemporary();
+    RefPtr<RegisterID> thisRegister = generator.newTemporary();
+    int identifierStart = divot() - startOffset();
+    generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
+    generator.emitResolveWithBase(thisRegister.get(), func.get(), m_ident);
+    return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallBracketNode ----------------------------------
+
+RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> base = generator.emitNode(m_base);
+    RegisterID* property = generator.emitNode(m_subscript);
+    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+    RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
+    RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
+    return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallDotNode ----------------------------------
+
+RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> function = generator.tempDestination(dst);
+    RefPtr<RegisterID> thisRegister = generator.newTemporary();
+    generator.emitNode(thisRegister.get(), m_base);
+    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+    generator.emitMethodCheck();
+    generator.emitGetById(function.get(), thisRegister.get(), m_ident);
+    return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+}
+
+RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<Label> realCall = generator.newLabel();
+    RefPtr<Label> end = generator.newLabel();
+    RefPtr<RegisterID> base = generator.emitNode(m_base);
+    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+    RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+    RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
+    generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
+    {
+        RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+        RefPtr<RegisterID> thisRegister = generator.newTemporary();
+        ArgumentListNode* oldList = m_args->m_listNode;
+        if (m_args->m_listNode && m_args->m_listNode->m_expr) {
+            generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
+            m_args->m_listNode = m_args->m_listNode->m_next;
+        } else
+            generator.emitLoad(thisRegister.get(), jsNull());
+
+        generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+        generator.emitJump(end.get());
+        m_args->m_listNode = oldList;
+    }
+    generator.emitLabel(realCall.get());
+    {
+        RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
+        generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+    }
+    generator.emitLabel(end.get());
+    return finalDestination.get();
+}
+    
+static bool areTrivialApplyArguments(ArgumentsNode* args)
+{
+    return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
+        || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
+}
+
+RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    // A few simple cases can be trivially handled as ordinary function calls.
+    // function.apply(), function.apply(arg) -> identical to function.call
+    // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
+    bool mayBeCall = areTrivialApplyArguments(m_args);
+
+    RefPtr<Label> realCall = generator.newLabel();
+    RefPtr<Label> end = generator.newLabel();
+    RefPtr<RegisterID> base = generator.emitNode(m_base);
+    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+    RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+    RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
+    generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
+    {
+        if (mayBeCall) {
+            RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+            RefPtr<RegisterID> thisRegister = generator.newTemporary();
+            ArgumentListNode* oldList = m_args->m_listNode;
+            if (m_args->m_listNode && m_args->m_listNode->m_expr) {
+                generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
+                m_args->m_listNode = m_args->m_listNode->m_next;
+                if (m_args->m_listNode) {
+                    ASSERT(m_args->m_listNode->m_expr->isSimpleArray());
+                    ASSERT(!m_args->m_listNode->m_next);
+                    m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData());
+                }
+            } else
+                generator.emitLoad(thisRegister.get(), jsNull());
+            generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+            m_args->m_listNode = oldList;
+        } else {
+            ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
+            RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
+            RefPtr<RegisterID> argsCountRegister = generator.newTemporary();
+            RefPtr<RegisterID> thisRegister = generator.newTemporary();
+            RefPtr<RegisterID> argsRegister = generator.newTemporary();
+            generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
+            ArgumentListNode* args = m_args->m_listNode->m_next;
+            bool isArgumentsApply = false;
+            if (args->m_expr->isResolveNode()) {
+                ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr);
+                isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier());
+                if (isArgumentsApply)
+                    generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments());
+            }
+            if (!isArgumentsApply)
+                generator.emitNode(argsRegister.get(), args->m_expr);
+            while ((args = args->m_next))
+                generator.emitNode(args->m_expr);
+
+            generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get());
+            generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
+        }
+        generator.emitJump(end.get());
+    }
+    generator.emitLabel(realCall.get());
+    {
+        RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
+        generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+    }
+    generator.emitLabel(end.get());
+    return finalDestination.get();
+}
+
+// ------------------------------ PostfixResolveNode ----------------------------------
+
+static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
+{
+    return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
+}
+
+static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
+{
+    if (srcDst == dst)
+        return generator.emitToJSNumber(dst, srcDst);
+    return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
+}
+
+RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (RegisterID* local = generator.registerFor(m_ident)) {
+        if (generator.isLocalConstant(m_ident)) {
+            if (dst == generator.ignoredResult())
+                return 0;
+            return generator.emitToJSNumber(generator.finalDestination(dst), local);
+        }
+
+        if (dst == generator.ignoredResult())
+            return emitPreIncOrDec(generator, local, m_operator);
+        return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
+    }
+
+    int index = 0;
+    size_t depth = 0;
+    JSObject* globalObject = 0;
+    if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
+        RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
+        RegisterID* oldValue;
+        if (dst == generator.ignoredResult()) {
+            oldValue = 0;
+            emitPreIncOrDec(generator, value.get(), m_operator);
+        } else {
+            oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
+        }
+        generator.emitPutScopedVar(depth, index, value.get(), globalObject);
+        return oldValue;
+    }
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    RefPtr<RegisterID> value = generator.newTemporary();
+    RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
+    RegisterID* oldValue;
+    if (dst == generator.ignoredResult()) {
+        oldValue = 0;
+        emitPreIncOrDec(generator, value.get(), m_operator);
+    } else {
+        oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
+    }
+    generator.emitPutById(base.get(), m_ident, value.get());
+    return oldValue;
+}
+
+// ------------------------------ PostfixBracketNode ----------------------------------
+
+RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> base = generator.emitNode(m_base);
+    RefPtr<RegisterID> property = generator.emitNode(m_subscript);
+
+    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+    RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
+    RegisterID* oldValue;
+    if (dst == generator.ignoredResult()) {
+        oldValue = 0;
+        if (m_operator == OpPlusPlus)
+            generator.emitPreInc(value.get());
+        else
+            generator.emitPreDec(value.get());
+    } else {
+        oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
+    }
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    generator.emitPutByVal(base.get(), property.get(), value.get());
+    return oldValue;
+}
+
+// ------------------------------ PostfixDotNode ----------------------------------
+
+RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> base = generator.emitNode(m_base);
+
+    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+    RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
+    RegisterID* oldValue;
+    if (dst == generator.ignoredResult()) {
+        oldValue = 0;
+        if (m_operator == OpPlusPlus)
+            generator.emitPreInc(value.get());
+        else
+            generator.emitPreDec(value.get());
+    } else {
+        oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
+    }
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    generator.emitPutById(base.get(), m_ident, value.get());
+    return oldValue;
+}
+
+// ------------------------------ PostfixErrorNode -----------------------------------
+
+RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+    return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
+        ? "Postfix ++ operator applied to value that is not a reference."
+        : "Postfix -- operator applied to value that is not a reference.");
+}
+
+// ------------------------------ DeleteResolveNode -----------------------------------
+
+RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (generator.registerFor(m_ident))
+        return generator.emitLoad(generator.finalDestination(dst), false);
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
+    return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
+}
+
+// ------------------------------ DeleteBracketNode -----------------------------------
+
+RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> r0 = generator.emitNode(m_base);
+    RegisterID* r1 = generator.emitNode(m_subscript);
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
+}
+
+// ------------------------------ DeleteDotNode -----------------------------------
+
+RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RegisterID* r0 = generator.emitNode(m_base);
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
+}
+
+// ------------------------------ DeleteValueNode -----------------------------------
+
+RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitNode(generator.ignoredResult(), m_expr);
+
+    // delete on a non-location expression ignores the value and returns true
+    return generator.emitLoad(generator.finalDestination(dst), true);
+}
+
+// ------------------------------ VoidNode -------------------------------------
+
+RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult()) {
+        generator.emitNode(generator.ignoredResult(), m_expr);
+        return 0;
+    }
+    RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
+    return generator.emitLoad(dst, jsUndefined());
+}
+
+// ------------------------------ TypeOfValueNode -----------------------------------
+
+RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (RegisterID* local = generator.registerFor(m_ident)) {
+        if (dst == generator.ignoredResult())
+            return 0;
+        return generator.emitTypeOf(generator.finalDestination(dst), local);
+    }
+
+    RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
+    generator.emitGetById(scratch.get(), scratch.get(), m_ident);
+    if (dst == generator.ignoredResult())
+        return 0;
+    return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
+}
+
+// ------------------------------ TypeOfValueNode -----------------------------------
+
+RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult()) {
+        generator.emitNode(generator.ignoredResult(), m_expr);
+        return 0;
+    }
+    RefPtr<RegisterID> src = generator.emitNode(m_expr);
+    return generator.emitTypeOf(generator.finalDestination(dst), src.get());
+}
+
+// ------------------------------ PrefixResolveNode ----------------------------------
+
+RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (RegisterID* local = generator.registerFor(m_ident)) {
+        if (generator.isLocalConstant(m_ident)) {
+            if (dst == generator.ignoredResult())
+                return 0;
+            RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
+            return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
+        }
+
+        emitPreIncOrDec(generator, local, m_operator);
+        return generator.moveToDestinationIfNeeded(dst, local);
+    }
+
+    int index = 0;
+    size_t depth = 0;
+    JSObject* globalObject = 0;
+    if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
+        RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
+        emitPreIncOrDec(generator, propDst.get(), m_operator);
+        generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
+        return generator.moveToDestinationIfNeeded(dst, propDst.get());
+    }
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+    RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
+    emitPreIncOrDec(generator, propDst.get(), m_operator);
+    generator.emitPutById(base.get(), m_ident, propDst.get());
+    return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+// ------------------------------ PrefixBracketNode ----------------------------------
+
+RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> base = generator.emitNode(m_base);
+    RefPtr<RegisterID> property = generator.emitNode(m_subscript);
+    RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+
+    generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
+    RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
+    if (m_operator == OpPlusPlus)
+        generator.emitPreInc(value);
+    else
+        generator.emitPreDec(value);
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    generator.emitPutByVal(base.get(), property.get(), value);
+    return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+// ------------------------------ PrefixDotNode ----------------------------------
+
+RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> base = generator.emitNode(m_base);
+    RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+
+    generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
+    RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
+    if (m_operator == OpPlusPlus)
+        generator.emitPreInc(value);
+    else
+        generator.emitPreDec(value);
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    generator.emitPutById(base.get(), m_ident, value);
+    return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+// ------------------------------ PrefixErrorNode -----------------------------------
+
+RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+    return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
+        ? "Prefix ++ operator applied to value that is not a reference."
+        : "Prefix -- operator applied to value that is not a reference.");
+}
+
+// ------------------------------ Unary Operation Nodes -----------------------------------
+
+RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RegisterID* src = generator.emitNode(m_expr);
+    return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
+}
+
+
+// ------------------------------ LogicalNotNode -----------------------------------
+
+void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
+{
+    ASSERT(expr()->hasConditionContextCodegen());
+
+    // reverse the true and false targets
+    generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, !fallThroughMeansTrue);
+}
+
+
+// ------------------------------ Binary Operation Nodes -----------------------------------
+
+// BinaryOpNode::emitStrcat:
+//
+// This node generates an op_strcat operation.  This opcode can handle concatenation of three or
+// more values, where we can determine a set of separate op_add operations would be operating on
+// string values.
+//
+// This function expects to be operating on a graph of AST nodes looking something like this:
+//
+//     (a)...     (b)
+//          \   /
+//           (+)     (c)
+//              \   /
+//      [d]     ((+))
+//         \    /
+//          [+=]
+//
+// The assignment operation is optional, if it exists the register holding the value on the
+// lefthand side of the assignment should be passing as the optional 'lhs' argument.
+//
+// The method should be called on the node at the root of the tree of regular binary add
+// operations (marked in the diagram with a double set of parentheses).  This node must
+// be performing a string concatenation (determined by statically detecting that at least
+// one child must be a string).  
+//
+// Since the minimum number of values being concatenated together is expected to be 3, if
+// a lhs to a concatenating assignment is not provided then the  root add should have at
+// least one left child that is also an add that can be determined to be operating on strings.
+//
+RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
+{
+    ASSERT(isAdd());
+    ASSERT(resultDescriptor().definitelyIsString());
+
+    // Create a list of expressions for all the adds in the tree of nodes we can convert into
+    // a string concatenation.  The rightmost node (c) is added first.  The rightmost node is
+    // added first, and the leftmost child is never added, so the vector produced for the
+    // example above will be [ c, b ].
+    Vector<ExpressionNode*, 16> reverseExpressionList;
+    reverseExpressionList.append(m_expr2);
+
+    // Examine the left child of the add.  So long as this is a string add, add its right-child
+    // to the list, and keep processing along the left fork.
+    ExpressionNode* leftMostAddChild = m_expr1;
+    while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
+        reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
+        leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
+    }
+
+    Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
+
+    // If there is an assignment, allocate a temporary to hold the lhs after conversion.
+    // We could possibly avoid this (the lhs is converted last anyway, we could let the
+    // op_strcat node handle its conversion if required).
+    if (lhs)
+        temporaryRegisters.append(generator.newTemporary());
+
+    // Emit code for the leftmost node ((a) in the example).
+    temporaryRegisters.append(generator.newTemporary());
+    RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
+    generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
+
+    // Note on ordering of conversions:
+    //
+    // We maintain the same ordering of conversions as we would see if the concatenations
+    // was performed as a sequence of adds (otherwise this optimization could change
+    // behaviour should an object have been provided a valueOf or toString method).
+    //
+    // Considering the above example, the sequnce of execution is:
+    //     * evaluate operand (a)
+    //     * evaluate operand (b)
+    //     * convert (a) to primitive   <-  (this would be triggered by the first add)
+    //     * convert (b) to primitive   <-  (ditto)
+    //     * evaluate operand (c)
+    //     * convert (c) to primitive   <-  (this would be triggered by the second add)
+    // And optionally, if there is an assignment:
+    //     * convert (d) to primitive   <-  (this would be triggered by the assigning addition)
+    //
+    // As such we do not plant an op to convert the leftmost child now.  Instead, use
+    // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
+    // once the second node has been generated.  However, if the leftmost child is an
+    // immediate we can trivially determine that no conversion will be required.
+    // If this is the case
+    if (leftMostAddChild->isString())
+        leftMostAddChildTempRegister = 0;
+
+    while (reverseExpressionList.size()) {
+        ExpressionNode* node = reverseExpressionList.last();
+        reverseExpressionList.removeLast();
+
+        // Emit the code for the current node.
+        temporaryRegisters.append(generator.newTemporary());
+        generator.emitNode(temporaryRegisters.last().get(), node);
+
+        // On the first iteration of this loop, when we first reach this point we have just
+        // generated the second node, which means it is time to convert the leftmost operand.
+        if (leftMostAddChildTempRegister) {
+            generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
+            leftMostAddChildTempRegister = 0; // Only do this once.
+        }
+        // Plant a conversion for this node, if necessary.
+        if (!node->isString())
+            generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
+    }
+    ASSERT(temporaryRegisters.size() >= 3);
+
+    // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
+    // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
+    if (emitExpressionInfoForMe)
+        generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
+
+    // If there is an assignment convert the lhs now.  This will also copy lhs to
+    // the temporary register we allocated for it.
+    if (lhs)
+        generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
+
+    return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
+}
+
+RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    OpcodeID opcodeID = this->opcodeID();
+
+    if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString())
+        return emitStrcat(generator, dst);
+
+    if (opcodeID == op_neq) {
+        if (m_expr1->isNull() || m_expr2->isNull()) {
+            RefPtr<RegisterID> src = generator.tempDestination(dst);
+            generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
+            return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
+        }
+    }
+
+    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+    RegisterID* src2 = generator.emitNode(m_expr2);
+    return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
+}
+
+RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (m_expr1->isNull() || m_expr2->isNull()) {
+        RefPtr<RegisterID> src = generator.tempDestination(dst);
+        generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
+        return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
+    }
+
+    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+    RegisterID* src2 = generator.emitNode(m_expr2);
+    return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+    RegisterID* src2 = generator.emitNode(m_expr2);
+    return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+    RegisterID* src2 = generator.emitNode(m_expr2);
+    return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
+}
+
+RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+    RegisterID* src2 = generator.emitNode(m_expr2);
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
+}
+
+RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
+    RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    generator.emitGetByIdExceptionInfo(op_instanceof);
+    RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
+}
+
+// ------------------------------ LogicalOpNode ----------------------------
+
+RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> temp = generator.tempDestination(dst);
+    RefPtr<Label> target = generator.newLabel();
+    
+    generator.emitNode(temp.get(), m_expr1);
+    if (m_operator == OpLogicalAnd)
+        generator.emitJumpIfFalse(temp.get(), target.get());
+    else
+        generator.emitJumpIfTrue(temp.get(), target.get());
+    generator.emitNode(temp.get(), m_expr2);
+    generator.emitLabel(target.get());
+
+    return generator.moveToDestinationIfNeeded(dst, temp.get());
+}
+
+void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
+{
+    if (m_expr1->hasConditionContextCodegen()) {
+        RefPtr<Label> afterExpr1 = generator.newLabel();
+        if (m_operator == OpLogicalAnd)
+            generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, true);
+        else 
+            generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), false);
+        generator.emitLabel(afterExpr1.get());
+    } else {
+        RegisterID* temp = generator.emitNode(m_expr1);
+        if (m_operator == OpLogicalAnd)
+            generator.emitJumpIfFalse(temp, falseTarget);
+        else
+            generator.emitJumpIfTrue(temp, trueTarget);
+    }
+
+    if (m_expr2->hasConditionContextCodegen())
+        generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMeansTrue);
+    else {
+        RegisterID* temp = generator.emitNode(m_expr2);
+        if (fallThroughMeansTrue)
+            generator.emitJumpIfFalse(temp, falseTarget);
+        else
+            generator.emitJumpIfTrue(temp, trueTarget);
+    }
+}
+
+// ------------------------------ ConditionalNode ------------------------------
+
+RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> newDst = generator.finalDestination(dst);
+    RefPtr<Label> beforeElse = generator.newLabel();
+    RefPtr<Label> afterElse = generator.newLabel();
+
+    if (m_logical->hasConditionContextCodegen()) {
+        RefPtr<Label> beforeThen = generator.newLabel();
+        generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), true);
+        generator.emitLabel(beforeThen.get());
+    } else {
+        RegisterID* cond = generator.emitNode(m_logical);
+        generator.emitJumpIfFalse(cond, beforeElse.get());
+    }
+
+    generator.emitNode(newDst.get(), m_expr1);
+    generator.emitJump(afterElse.get());
+
+    generator.emitLabel(beforeElse.get());
+    generator.emitNode(newDst.get(), m_expr2);
+
+    generator.emitLabel(afterElse.get());
+
+    return newDst.get();
+}
+
+// ------------------------------ ReadModifyResolveNode -----------------------------------
+
+// FIXME: should this be moved to be a method on BytecodeGenerator?
+static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
+{
+    OpcodeID opcodeID;
+    switch (oper) {
+        case OpMultEq:
+            opcodeID = op_mul;
+            break;
+        case OpDivEq:
+            opcodeID = op_div;
+            break;
+        case OpPlusEq:
+            if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
+                return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
+            opcodeID = op_add;
+            break;
+        case OpMinusEq:
+            opcodeID = op_sub;
+            break;
+        case OpLShift:
+            opcodeID = op_lshift;
+            break;
+        case OpRShift:
+            opcodeID = op_rshift;
+            break;
+        case OpURShift:
+            opcodeID = op_urshift;
+            break;
+        case OpAndEq:
+            opcodeID = op_bitand;
+            break;
+        case OpXOrEq:
+            opcodeID = op_bitxor;
+            break;
+        case OpOrEq:
+            opcodeID = op_bitor;
+            break;
+        case OpModEq:
+            opcodeID = op_mod;
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+            return dst;
+    }
+
+    RegisterID* src2 = generator.emitNode(m_right);
+
+    // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
+    // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
+    if (emitExpressionInfoForMe)
+        generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
+
+    return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
+}
+
+RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (RegisterID* local = generator.registerFor(m_ident)) {
+        if (generator.isLocalConstant(m_ident)) {
+            return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+        }
+        
+        if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
+            RefPtr<RegisterID> result = generator.newTemporary();
+            generator.emitMove(result.get(), local);
+            emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+            generator.emitMove(local, result.get());
+            return generator.moveToDestinationIfNeeded(dst, result.get());
+        }
+        
+        RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+        return generator.moveToDestinationIfNeeded(dst, result);
+    }
+
+    int index = 0;
+    size_t depth = 0;
+    JSObject* globalObject = 0;
+    if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
+        RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
+        RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+        generator.emitPutScopedVar(depth, index, result, globalObject);
+        return result;
+    }
+
+    RefPtr<RegisterID> src1 = generator.tempDestination(dst);
+    generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
+    RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
+    RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
+    return generator.emitPutById(base.get(), m_ident, result);
+}
+
+// ------------------------------ AssignResolveNode -----------------------------------
+
+RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (RegisterID* local = generator.registerFor(m_ident)) {
+        if (generator.isLocalConstant(m_ident))
+            return generator.emitNode(dst, m_right);
+        
+        RegisterID* result = generator.emitNode(local, m_right);
+        return generator.moveToDestinationIfNeeded(dst, result);
+    }
+
+    int index = 0;
+    size_t depth = 0;
+    JSObject* globalObject = 0;
+    if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
+        if (dst == generator.ignoredResult())
+            dst = 0;
+        RegisterID* value = generator.emitNode(dst, m_right);
+        generator.emitPutScopedVar(depth, index, value, globalObject);
+        return value;
+    }
+
+    RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
+    if (dst == generator.ignoredResult())
+        dst = 0;
+    RegisterID* value = generator.emitNode(dst, m_right);
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    return generator.emitPutById(base.get(), m_ident, value);
+}
+
+// ------------------------------ AssignDotNode -----------------------------------
+
+RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
+    RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
+    RegisterID* result = generator.emitNode(value.get(), m_right);
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    generator.emitPutById(base.get(), m_ident, result);
+    return generator.moveToDestinationIfNeeded(dst, result);
+}
+
+// ------------------------------ ReadModifyDotNode -----------------------------------
+
+RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
+
+    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+    RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    return generator.emitPutById(base.get(), m_ident, updatedValue);
+}
+
+// ------------------------------ AssignErrorNode -----------------------------------
+
+RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+    return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
+}
+
+// ------------------------------ AssignBracketNode -----------------------------------
+
+RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
+    RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
+    RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
+    RegisterID* result = generator.emitNode(value.get(), m_right);
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    generator.emitPutByVal(base.get(), property.get(), result);
+    return generator.moveToDestinationIfNeeded(dst, result);
+}
+
+// ------------------------------ ReadModifyBracketNode -----------------------------------
+
+RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
+    RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
+
+    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+    RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
+    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    generator.emitPutByVal(base.get(), property.get(), updatedValue);
+
+    return updatedValue;
+}
+
+// ------------------------------ CommaNode ------------------------------------
+
+RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    ASSERT(m_expressions.size() > 1);
+    for (size_t i = 0; i < m_expressions.size() - 1; i++)
+        generator.emitNode(generator.ignoredResult(), m_expressions[i]);
+    return generator.emitNode(dst, m_expressions.last());
+}
+
+// ------------------------------ ConstDeclNode ------------------------------------
+
+RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
+{
+    if (RegisterID* local = generator.constRegisterFor(m_ident)) {
+        if (!m_init)
+            return local;
+
+        return generator.emitNode(local, m_init);
+    }
+
+    if (generator.codeType() != EvalCode) {
+        if (m_init)
+            return generator.emitNode(m_init);
+        else
+            return generator.emitResolve(generator.newTemporary(), m_ident);
+    }
+    // FIXME: While this code should only be hit in eval code, it will potentially
+    // assign to the wrong base if m_ident exists in an intervening dynamic scope.
+    RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
+    RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
+    return generator.emitPutById(base.get(), m_ident, value);
+}
+
+RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+    RegisterID* result = 0;
+    for (ConstDeclNode* n = this; n; n = n->m_next)
+        result = n->emitCodeSingle(generator);
+
+    return result;
+}
+
+// ------------------------------ ConstStatementNode -----------------------------
+
+RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    return generator.emitNode(m_next);
+}
+
+// ------------------------------ SourceElements -------------------------------
+
+
+inline StatementNode* SourceElements::lastStatement() const
+{
+    size_t size = m_statements.size();
+    return size ? m_statements[size - 1] : 0;
+}
+
+inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    size_t size = m_statements.size();
+    for (size_t i = 0; i < size; ++i)
+        generator.emitNode(dst, m_statements[i]);
+}
+
+// ------------------------------ BlockNode ------------------------------------
+
+inline StatementNode* BlockNode::lastStatement() const
+{
+    return m_statements ? m_statements->lastStatement() : 0;
+}
+
+RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (m_statements)
+        m_statements->emitBytecode(generator, dst);
+    return 0;
+}
+
+// ------------------------------ EmptyStatementNode ---------------------------
+
+RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    return dst;
+}
+
+// ------------------------------ DebuggerStatementNode ---------------------------
+
+RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
+    return dst;
+}
+
+// ------------------------------ ExprStatementNode ----------------------------
+
+RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    ASSERT(m_expr);
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 
+    return generator.emitNode(dst, m_expr);
+}
+
+// ------------------------------ VarStatementNode ----------------------------
+
+RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+    ASSERT(m_expr);
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    return generator.emitNode(m_expr);
+}
+
+// ------------------------------ IfNode ---------------------------------------
+
+RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    
+    RefPtr<Label> afterThen = generator.newLabel();
+
+    if (m_condition->hasConditionContextCodegen()) {
+        RefPtr<Label> beforeThen = generator.newLabel();
+        generator.emitNodeInConditionContext(m_condition, beforeThen.get(), afterThen.get(), true);
+        generator.emitLabel(beforeThen.get());
+    } else {
+        RegisterID* cond = generator.emitNode(m_condition);
+        generator.emitJumpIfFalse(cond, afterThen.get());
+    }
+
+    generator.emitNode(dst, m_ifBlock);
+    generator.emitLabel(afterThen.get());
+
+    // FIXME: This should return the last statement executed so that it can be returned as a Completion.
+    return 0;
+}
+
+// ------------------------------ IfElseNode ---------------------------------------
+
+RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    
+    RefPtr<Label> beforeElse = generator.newLabel();
+    RefPtr<Label> afterElse = generator.newLabel();
+
+    if (m_condition->hasConditionContextCodegen()) {
+        RefPtr<Label> beforeThen = generator.newLabel();
+        generator.emitNodeInConditionContext(m_condition, beforeThen.get(), beforeElse.get(), true);
+        generator.emitLabel(beforeThen.get());
+    } else {
+        RegisterID* cond = generator.emitNode(m_condition);
+        generator.emitJumpIfFalse(cond, beforeElse.get());
+    }
+
+    generator.emitNode(dst, m_ifBlock);
+    generator.emitJump(afterElse.get());
+
+    generator.emitLabel(beforeElse.get());
+
+    generator.emitNode(dst, m_elseBlock);
+
+    generator.emitLabel(afterElse.get());
+
+    // FIXME: This should return the last statement executed so that it can be returned as a Completion.
+    return 0;
+}
+
+// ------------------------------ DoWhileNode ----------------------------------
+
+RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+    RefPtr<Label> topOfLoop = generator.newLabel();
+    generator.emitLabel(topOfLoop.get());
+
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+   
+    RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
+
+    generator.emitLabel(scope->continueTarget());
+    generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
+    if (m_expr->hasConditionContextCodegen())
+        generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false);
+    else {
+        RegisterID* cond = generator.emitNode(m_expr);
+        generator.emitJumpIfTrue(cond, topOfLoop.get());
+    }
+
+    generator.emitLabel(scope->breakTarget());
+    return result.get();
+}
+
+// ------------------------------ WhileNode ------------------------------------
+
+RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+    generator.emitJump(scope->continueTarget());
+
+    RefPtr<Label> topOfLoop = generator.newLabel();
+    generator.emitLabel(topOfLoop.get());
+    
+    generator.emitNode(dst, m_statement);
+
+    generator.emitLabel(scope->continueTarget());
+    generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
+
+    if (m_expr->hasConditionContextCodegen())
+        generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false);
+    else {
+        RegisterID* cond = generator.emitNode(m_expr);
+        generator.emitJumpIfTrue(cond, topOfLoop.get());
+    }
+
+    generator.emitLabel(scope->breakTarget());
+    
+    // FIXME: This should return the last statement executed so that it can be returned as a Completion
+    return 0;
+}
+
+// ------------------------------ ForNode --------------------------------------
+
+RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+    if (m_expr1)
+        generator.emitNode(generator.ignoredResult(), m_expr1);
+
+    RefPtr<Label> condition = generator.newLabel();
+    generator.emitJump(condition.get());
+
+    RefPtr<Label> topOfLoop = generator.newLabel();
+    generator.emitLabel(topOfLoop.get());
+
+    RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
+
+    generator.emitLabel(scope->continueTarget());
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    if (m_expr3)
+        generator.emitNode(generator.ignoredResult(), m_expr3);
+
+    generator.emitLabel(condition.get());
+    if (m_expr2) {
+        if (m_expr2->hasConditionContextCodegen())
+            generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), false);
+        else {
+            RegisterID* cond = generator.emitNode(m_expr2);
+            generator.emitJumpIfTrue(cond, topOfLoop.get());
+        }
+    } else
+        generator.emitJump(topOfLoop.get());
+
+    generator.emitLabel(scope->breakTarget());
+    return result.get();
+}
+
+// ------------------------------ ForInNode ------------------------------------
+
+RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+    if (!m_lexpr->isLocation())
+        return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
+
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+    if (m_init)
+        generator.emitNode(generator.ignoredResult(), m_init);
+
+    RefPtr<RegisterID> base = generator.newTemporary();
+    generator.emitNode(base.get(), m_expr);
+    RefPtr<RegisterID> i = generator.newTemporary();
+    RefPtr<RegisterID> size = generator.newTemporary();
+    RefPtr<RegisterID> expectedSubscript;
+    RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget());
+    generator.emitJump(scope->continueTarget());
+
+    RefPtr<Label> loopStart = generator.newLabel();
+    generator.emitLabel(loopStart.get());
+
+    RegisterID* propertyName;
+    bool optimizedForinAccess = false;
+    if (m_lexpr->isResolveNode()) {
+        const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
+        propertyName = generator.registerFor(ident);
+        if (!propertyName) {
+            propertyName = generator.newTemporary();
+            RefPtr<RegisterID> protect = propertyName;
+            RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
+
+            generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+            generator.emitPutById(base, ident, propertyName);
+        } else {
+            expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
+            generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName);
+            optimizedForinAccess = true;
+        }
+    } else if (m_lexpr->isDotAccessorNode()) {
+        DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
+        const Identifier& ident = assignNode->identifier();
+        propertyName = generator.newTemporary();
+        RefPtr<RegisterID> protect = propertyName;
+        RegisterID* base = generator.emitNode(assignNode->base());
+
+        generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
+        generator.emitPutById(base, ident, propertyName);
+    } else {
+        ASSERT(m_lexpr->isBracketAccessorNode());
+        BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
+        propertyName = generator.newTemporary();
+        RefPtr<RegisterID> protect = propertyName;
+        RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
+        RegisterID* subscript = generator.emitNode(assignNode->subscript());
+        
+        generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
+        generator.emitPutByVal(base.get(), subscript, propertyName);
+    }   
+
+    generator.emitNode(dst, m_statement);
+
+    if (optimizedForinAccess)
+        generator.popOptimisedForIn();
+
+    generator.emitLabel(scope->continueTarget());
+    generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    generator.emitLabel(scope->breakTarget());
+    return dst;
+}
+
+// ------------------------------ ContinueNode ---------------------------------
+
+// ECMA 12.7
+RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    
+    LabelScope* scope = generator.continueTarget(m_ident);
+
+    if (!scope)
+        return m_ident.isEmpty()
+            ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
+            : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
+
+    generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
+    return dst;
+}
+
+// ------------------------------ BreakNode ------------------------------------
+
+// ECMA 12.8
+RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    
+    LabelScope* scope = generator.breakTarget(m_ident);
+    
+    if (!scope)
+        return m_ident.isEmpty()
+            ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
+            : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
+
+    generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
+    return dst;
+}
+
+// ------------------------------ ReturnNode -----------------------------------
+
+RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    if (generator.codeType() != FunctionCode)
+        return emitThrowError(generator, SyntaxError, "Invalid return statement.");
+
+    if (dst == generator.ignoredResult())
+        dst = 0;
+    RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
+    RefPtr<RegisterID> returnRegister;
+    if (generator.scopeDepth()) {
+        RefPtr<Label> l0 = generator.newLabel();
+        if (generator.hasFinaliser() && !r0->isTemporary()) {
+            returnRegister = generator.emitMove(generator.newTemporary(), r0);
+            r0 = returnRegister.get();
+        }
+        generator.emitJumpScopes(l0.get(), 0);
+        generator.emitLabel(l0.get());
+    }
+    generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
+    return generator.emitReturn(r0);
+}
+
+// ------------------------------ WithNode -------------------------------------
+
+RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    
+    RefPtr<RegisterID> scope = generator.newTemporary();
+    generator.emitNode(scope.get(), m_expr); // scope must be protected until popped
+    generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
+    generator.emitPushScope(scope.get());
+    RegisterID* result = generator.emitNode(dst, m_statement);
+    generator.emitPopScope();
+    return result;
+}
+
+// ------------------------------ CaseClauseNode --------------------------------
+
+inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (m_statements)
+        m_statements->emitBytecode(generator, dst);
+}
+
+// ------------------------------ CaseBlockNode --------------------------------
+
+enum SwitchKind { 
+    SwitchUnset = 0,
+    SwitchNumber = 1, 
+    SwitchString = 2, 
+    SwitchNeither = 3 
+};
+
+static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
+{
+    for (; list; list = list->getNext()) {
+        ExpressionNode* clauseExpression = list->getClause()->expr();
+        literalVector.append(clauseExpression);
+        if (clauseExpression->isNumber()) {
+            double value = static_cast<NumberNode*>(clauseExpression)->value();
+            int32_t intVal = static_cast<int32_t>(value);
+            if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
+                typeForTable = SwitchNeither;
+                break;
+            }
+            if (intVal < min_num)
+                min_num = intVal;
+            if (intVal > max_num)
+                max_num = intVal;
+            typeForTable = SwitchNumber;
+            continue;
+        }
+        if (clauseExpression->isString()) {
+            if (typeForTable & ~SwitchString) {
+                typeForTable = SwitchNeither;
+                break;
+            }
+            const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
+            if (singleCharacterSwitch &= value.size() == 1) {
+                int32_t intVal = value.rep()->data()[0];
+                if (intVal < min_num)
+                    min_num = intVal;
+                if (intVal > max_num)
+                    max_num = intVal;
+            }
+            typeForTable = SwitchString;
+            continue;
+        }
+        typeForTable = SwitchNeither;
+        break;        
+    }
+}
+    
+SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
+{
+    SwitchKind typeForTable = SwitchUnset;
+    bool singleCharacterSwitch = true;
+    
+    processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
+    processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
+    
+    if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
+        return SwitchInfo::SwitchNone;
+    
+    if (typeForTable == SwitchNumber) {
+        int32_t range = max_num - min_num;
+        if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
+            return SwitchInfo::SwitchImmediate;
+        return SwitchInfo::SwitchNone;
+    } 
+    
+    ASSERT(typeForTable == SwitchString);
+    
+    if (singleCharacterSwitch) {
+        int32_t range = max_num - min_num;
+        if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
+            return SwitchInfo::SwitchCharacter;
+    }
+
+    return SwitchInfo::SwitchString;
+}
+
+RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
+{
+    RefPtr<Label> defaultLabel;
+    Vector<RefPtr<Label>, 8> labelVector;
+    Vector<ExpressionNode*, 8> literalVector;
+    int32_t min_num = std::numeric_limits<int32_t>::max();
+    int32_t max_num = std::numeric_limits<int32_t>::min();
+    SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
+
+    if (switchType != SwitchInfo::SwitchNone) {
+        // Prepare the various labels
+        for (uint32_t i = 0; i < literalVector.size(); i++)
+            labelVector.append(generator.newLabel());
+        defaultLabel = generator.newLabel();
+        generator.beginSwitch(switchExpression, switchType);
+    } else {
+        // Setup jumps
+        for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
+            RefPtr<RegisterID> clauseVal = generator.newTemporary();
+            generator.emitNode(clauseVal.get(), list->getClause()->expr());
+            generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
+            labelVector.append(generator.newLabel());
+            generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
+        }
+        
+        for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
+            RefPtr<RegisterID> clauseVal = generator.newTemporary();
+            generator.emitNode(clauseVal.get(), list->getClause()->expr());
+            generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
+            labelVector.append(generator.newLabel());
+            generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
+        }
+        defaultLabel = generator.newLabel();
+        generator.emitJump(defaultLabel.get());
+    }
+
+    RegisterID* result = 0;
+
+    size_t i = 0;
+    for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
+        generator.emitLabel(labelVector[i++].get());
+        list->getClause()->emitBytecode(generator, dst);
+    }
+
+    if (m_defaultClause) {
+        generator.emitLabel(defaultLabel.get());
+        m_defaultClause->emitBytecode(generator, dst);
+    }
+
+    for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
+        generator.emitLabel(labelVector[i++].get());
+        list->getClause()->emitBytecode(generator, dst);
+    }
+    if (!m_defaultClause)
+        generator.emitLabel(defaultLabel.get());
+
+    ASSERT(i == labelVector.size());
+    if (switchType != SwitchInfo::SwitchNone) {
+        ASSERT(labelVector.size() == literalVector.size());
+        generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
+    }
+    return result;
+}
+
+// ------------------------------ SwitchNode -----------------------------------
+
+RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+    
+    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
+
+    RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
+    RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
+
+    generator.emitLabel(scope->breakTarget());
+    return r1;
+}
+
+// ------------------------------ LabelNode ------------------------------------
+
+RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+    if (generator.breakTarget(m_name))
+        return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
+
+    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
+    RegisterID* r0 = generator.emitNode(dst, m_statement);
+
+    generator.emitLabel(scope->breakTarget());
+    return r0;
+}
+
+// ------------------------------ ThrowNode ------------------------------------
+
+RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+    if (dst == generator.ignoredResult())
+        dst = 0;
+    RefPtr<RegisterID> expr = generator.emitNode(m_expr);
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+    generator.emitThrow(expr.get());
+    return 0;
+}
+
+// ------------------------------ TryNode --------------------------------------
+
+RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    // NOTE: The catch and finally blocks must be labeled explicitly, so the
+    // optimizer knows they may be jumped to from anywhere.
+
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+    RefPtr<Label> tryStartLabel = generator.newLabel();
+    RefPtr<Label> finallyStart;
+    RefPtr<RegisterID> finallyReturnAddr;
+    if (m_finallyBlock) {
+        finallyStart = generator.newLabel();
+        finallyReturnAddr = generator.newTemporary();
+        generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
+    }
+
+    generator.emitLabel(tryStartLabel.get());
+    generator.emitNode(dst, m_tryBlock);
+
+    if (m_catchBlock) {
+        RefPtr<Label> catchEndLabel = generator.newLabel();
+        
+        // Normal path: jump over the catch block.
+        generator.emitJump(catchEndLabel.get());
+
+        // Uncaught exception path: the catch block.
+        RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
+        RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
+        if (m_catchHasEval) {
+            RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
+            generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
+            generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
+            generator.emitPushScope(exceptionRegister.get());
+        } else
+            generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
+        generator.emitNode(dst, m_catchBlock);
+        generator.emitPopScope();
+        generator.emitLabel(catchEndLabel.get());
+    }
+
+    if (m_finallyBlock) {
+        generator.popFinallyContext();
+        // there may be important registers live at the time we jump
+        // to a finally block (such as for a return or throw) so we
+        // ref the highest register ever used as a conservative
+        // approach to not clobbering anything important
+        RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
+        RefPtr<Label> finallyEndLabel = generator.newLabel();
+
+        // Normal path: invoke the finally block, then jump over it.
+        generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+        generator.emitJump(finallyEndLabel.get());
+
+        // Uncaught exception path: invoke the finally block, then re-throw the exception.
+        RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
+        RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
+        generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+        generator.emitThrow(tempExceptionRegister.get());
+
+        // The finally block.
+        generator.emitLabel(finallyStart.get());
+        generator.emitNode(dst, m_finallyBlock);
+        generator.emitSubroutineReturn(finallyReturnAddr.get());
+
+        generator.emitLabel(finallyEndLabel.get());
+    }
+
+    return dst;
+}
+
+// ------------------------------ ScopeNode -----------------------------
+
+inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (m_data->m_statements)
+        m_data->m_statements->emitBytecode(generator, dst);
+}
+
+// ------------------------------ ProgramNode -----------------------------
+
+RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+    generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
+
+    RefPtr<RegisterID> dstRegister = generator.newTemporary();
+    generator.emitLoad(dstRegister.get(), jsUndefined());
+    emitStatementsBytecode(generator, dstRegister.get());
+
+    generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
+    generator.emitEnd(dstRegister.get());
+    return 0;
+}
+
+// ------------------------------ EvalNode -----------------------------
+
+RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+    generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
+
+    RefPtr<RegisterID> dstRegister = generator.newTemporary();
+    generator.emitLoad(dstRegister.get(), jsUndefined());
+    emitStatementsBytecode(generator, dstRegister.get());
+
+    generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
+    generator.emitEnd(dstRegister.get());
+    return 0;
+}
+
+// ------------------------------ FunctionBodyNode -----------------------------
+
+RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+    generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
+    emitStatementsBytecode(generator, generator.ignoredResult());
+    StatementNode* singleStatement = this->singleStatement();
+    if (singleStatement && singleStatement->isBlock()) {
+        StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
+        if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
+            return 0;
+    }
+
+    RegisterID* r0 = generator.emitLoad(0, jsUndefined());
+    generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
+    generator.emitReturn(r0);
+    return 0;
+}
+
+// ------------------------------ FuncDeclNode ---------------------------------
+
+RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult())
+        dst = 0;
+    return dst;
+}
+
+// ------------------------------ FuncExprNode ---------------------------------
+
+RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
+}
+
+} // namespace JSC
index 0223c2a13710bab0ddab29c59041b21b3448b96a..3532ad802cb220ae76a6230152080b999ceb8487 100644 (file)
@@ -35,7 +35,7 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class RegisterID : Noncopyable {
+    class RegisterID : public Noncopyable {
     public:
         RegisterID()
             : m_refCount(0)
     public:
         RegisterID()
             : m_refCount(0)
index 66817612f6071240dd5d432e4aa98146f8ec807f..d5fdfe9ddd63dc2f85376cdfe1f47096eff6d164 100644 (file)
--- a/config.h
+++ b/config.h
 
 #include <wtf/Platform.h>
 
 
 #include <wtf/Platform.h>
 
-#if PLATFORM(WIN_OS) && !defined(BUILDING_WX__) && !COMPILER(GCC)
+#if OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC)
 #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
 #define JS_EXPORTDATA __declspec(dllexport)
 #else
 #define JS_EXPORTDATA __declspec(dllimport)
 #endif
 #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
 #define JS_EXPORTDATA __declspec(dllexport)
 #else
 #define JS_EXPORTDATA __declspec(dllimport)
 #endif
+#define JS_EXPORTCLASS JS_EXPORTDATA
 #else
 #define JS_EXPORTDATA
 #else
 #define JS_EXPORTDATA
+#define JS_EXPORTCLASS
 #endif
 
 #endif
 
-#if PLATFORM(WIN_OS)
+#if OS(WINDOWS)
 
 // If we don't define these, they get defined in windef.h. 
 // We want to use std::min and std::max
 #define max max
 #define min min
 
 
 // If we don't define these, they get defined in windef.h. 
 // We want to use std::min and std::max
 #define max max
 #define min min
 
-#if !COMPILER(MSVC7) && !PLATFORM(WINCE)
+#if !COMPILER(MSVC7) && !OS(WINCE)
 // We need to define this before the first #include of stdlib.h or it won't contain rand_s.
 #ifndef _CRT_RAND_S
 #define _CRT_RAND_S
 // We need to define this before the first #include of stdlib.h or it won't contain rand_s.
 #ifndef _CRT_RAND_S
 #define _CRT_RAND_S
 
 #endif
 
 
 #endif
 
-#if PLATFORM(FREEBSD) || PLATFORM(OPENBSD)
+#if OS(FREEBSD) || OS(OPENBSD)
 #define HAVE_PTHREAD_NP_H 1
 #endif
 
 /* FIXME: if all platforms have these, do they really need #defines? */
 #define HAVE_STDINT_H 1
 #define HAVE_PTHREAD_NP_H 1
 #endif
 
 /* FIXME: if all platforms have these, do they really need #defines? */
 #define HAVE_STDINT_H 1
-#define HAVE_STRING_H 1
 
 #define WTF_CHANGES 1
 
 
 #define WTF_CHANGES 1
 
 #include <wtf/DisallowCType.h>
 #endif
 
 #include <wtf/DisallowCType.h>
 #endif
 
+#if PLATFORM(CHROMIUM)
+#if !defined(WTF_USE_V8)
+#define WTF_USE_V8 1
+#endif
+#endif /* PLATFORM(CHROMIUM) */
+
+#if !defined(WTF_USE_V8)
+#define WTF_USE_V8 0
+#endif /* !defined(WTF_USE_V8) */
+
+/* Using V8 implies not using JSC and vice versa */
+#define WTF_USE_JSC !WTF_USE_V8
diff --git a/create_rvct_stubs b/create_rvct_stubs
new file mode 100644 (file)
index 0000000..0c49c4f
--- /dev/null
@@ -0,0 +1,52 @@
+#! /usr/bin/perl -w
+#
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+use strict;
+
+my $file = $ARGV[0];
+shift;
+
+my $stub_template = "";
+my $stub = "";
+
+my $rtype = "";
+my $op = "";
+
+my $rtype_template = quotemeta("#rtype#");
+my $op_template = quotemeta("#op#");
+
+print STDERR "Creating RVCT stubs for $file \n";
+open(IN, $file) or die "No such file $file";
+
+while ( $_ = <IN> ) {
+    if ( /^RVCT\((.*)\)/ ) {
+        $stub_template .= $1 . "\n";
+    }
+    if ( /^DEFINE_STUB_FUNCTION\((.*), (.*)\)/ ) {
+        $stub = $stub_template;
+        $rtype = quotemeta($1);
+        $op = quotemeta($2);
+        $stub =~ s/$rtype_template/$rtype/g;
+        $stub =~ s/$op_template/$op/g;
+        $stub =~ s/\\\*/\*/g;
+        print $stub;
+    }
+}
+
+close(IN);
index 7d791e7c8155a962644ed0fbc2c82933005cfca1..1d2e4fb62bda317b6e7f36e02b42102946ef118b 100644 (file)
 #include "config.h"
 #include "Debugger.h"
 
 #include "config.h"
 #include "Debugger.h"
 
-#include "JSGlobalObject.h"
+#include "CollectorHeapIterator.h"
+#include "Error.h"
 #include "Interpreter.h"
 #include "Interpreter.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
 #include "Parser.h"
 #include "Parser.h"
+#include "Protect.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-Debugger::Debugger()
-{
-}
-
 Debugger::~Debugger()
 {
     HashSet<JSGlobalObject*>::iterator end = m_globalObjects.end();
 Debugger::~Debugger()
 {
     HashSet<JSGlobalObject*>::iterator end = m_globalObjects.end();
@@ -53,18 +53,60 @@ void Debugger::detach(JSGlobalObject* globalObject)
     globalObject->setDebugger(0);
 }
 
     globalObject->setDebugger(0);
 }
 
+void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
+{
+    // If JavaScript is running, it's not safe to recompile, since we'll end
+    // up throwing away code that is live on the stack.
+    ASSERT(!globalData->dynamicGlobalObject);
+    if (globalData->dynamicGlobalObject)
+        return;
+
+    typedef HashSet<FunctionExecutable*> FunctionExecutableSet;
+    typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;
+
+    FunctionExecutableSet functionExecutables;
+    SourceProviderMap sourceProviders;
+
+    LiveObjectIterator it = globalData->heap.primaryHeapBegin();
+    LiveObjectIterator heapEnd = globalData->heap.primaryHeapEnd();
+    for ( ; it != heapEnd; ++it) {
+        if (!(*it)->inherits(&JSFunction::info))
+            continue;
+
+        JSFunction* function = asFunction(*it);
+        if (function->executable()->isHostFunction())
+            continue;
+
+        FunctionExecutable* executable = function->jsExecutable();
+
+        // Check if the function is already in the set - if so,
+        // we've already retranslated it, nothing to do here.
+        if (!functionExecutables.add(executable).second)
+            continue;
+
+        ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec();
+        executable->recompile(exec);
+        if (function->scope().globalObject()->debugger() == this)
+            sourceProviders.add(executable->source().provider(), exec);
+    }
+
+    // Call sourceParsed() after reparsing all functions because it will execute
+    // JavaScript in the inspector.
+    SourceProviderMap::const_iterator end = sourceProviders.end();
+    for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter)
+        sourceParsed(iter->second, SourceCode(iter->first), -1, 0);
+}
+
 JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
 {
     CallFrame* globalCallFrame = globalObject->globalExec();
 
 JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
 {
     CallFrame* globalCallFrame = globalObject->globalExec();
 
-    int errLine;
-    UString errMsg;
-    SourceCode source = makeSource(script);
-    RefPtr<EvalNode> evalNode = globalObject->globalData()->parser->parse<EvalNode>(globalCallFrame, globalObject->debugger(), source, &errLine, &errMsg);
-    if (!evalNode)
-        return Error::create(globalCallFrame, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
+    RefPtr<EvalExecutable> eval = EvalExecutable::create(globalCallFrame, makeSource(script));
+    JSObject* error = eval->compile(globalCallFrame, globalCallFrame->scopeChain());
+    if (error)
+        return error;
 
 
-    return globalObject->globalData()->interpreter->execute(evalNode.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception);
+    return globalObject->globalData()->interpreter->execute(eval.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 98d09358cd62159fd371f70af6898e6f4553dab2..3b9bec4ac924f499155cc87836de142306c9cf0f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 #ifndef Debugger_h
 #define Debugger_h
 
 #ifndef Debugger_h
 #define Debugger_h
 
-#include "Protect.h"
+#include <wtf/HashSet.h>
 
 namespace JSC {
 
     class DebuggerCallFrame;
     class ExecState;
 
 namespace JSC {
 
     class DebuggerCallFrame;
     class ExecState;
+    class JSGlobalData;
     class JSGlobalObject;
     class JSGlobalObject;
+    class JSValue;
     class SourceCode;
     class UString;
 
     class Debugger {
     public:
     class SourceCode;
     class UString;
 
     class Debugger {
     public:
-        Debugger();
         virtual ~Debugger();
 
         void attach(JSGlobalObject*);
         virtual void detach(JSGlobalObject*);
 
         virtual ~Debugger();
 
         void attach(JSGlobalObject*);
         virtual void detach(JSGlobalObject*);
 
-        virtual void sourceParsed(ExecState*, const SourceCode&, int errorLine, const UString& errorMsg) = 0;
-        virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
-        virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
-        virtual void callEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
-        virtual void returnEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
+        virtual void sourceParsed(ExecState*, const SourceCode&, int errorLineNumber, const UString& errorMessage) = 0;
+        virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber, bool hasHandler) = 0;
+        virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
+        virtual void callEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
+        virtual void returnEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
 
 
-        virtual void willExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
-        virtual void didExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
-        virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0;
+        virtual void willExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
+        virtual void didExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
+        virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
+
+        void recompileAllJSFunctions(JSGlobalData*);
 
     private:
         HashSet<JSGlobalObject*> m_globalObjects;
     };
 
 
     private:
         HashSet<JSGlobalObject*> m_globalObjects;
     };
 
-    // This method exists only for backwards compatibility with existing
-    // WebScriptDebugger clients
+    // This function exists only for backwards compatibility with existing WebScriptDebugger clients.
     JSValue evaluateInGlobalCallFrame(const UString&, JSValue& exception, JSGlobalObject*);
 
 } // namespace JSC
     JSValue evaluateInGlobalCallFrame(const UString&, JSValue& exception, JSGlobalObject*);
 
 } // namespace JSC
index 4b2568f026c254966a3f2cabbbd30e38cfa58214..0444d23d204f8318a392555c5c57c56906a3b914 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -38,11 +38,12 @@ DebuggerActivation::DebuggerActivation(JSObject* activation)
     m_activation = static_cast<JSActivation*>(activation);
 }
 
     m_activation = static_cast<JSActivation*>(activation);
 }
 
-void DebuggerActivation::mark()
+void DebuggerActivation::markChildren(MarkStack& markStack)
 {
 {
-    JSObject::mark();
-    if (m_activation && !m_activation->marked())
-        m_activation->mark();
+    JSObject::markChildren(markStack);
+
+    if (m_activation)
+        markStack.append(m_activation);
 }
 
 UString DebuggerActivation::className() const
 }
 
 UString DebuggerActivation::className() const
@@ -70,24 +71,24 @@ bool DebuggerActivation::deleteProperty(ExecState* exec, const Identifier& prope
     return m_activation->deleteProperty(exec, propertyName);
 }
 
     return m_activation->deleteProperty(exec, propertyName);
 }
 
-void DebuggerActivation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void DebuggerActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    m_activation->getPropertyNames(exec, propertyNames);
+    m_activation->getPropertyNames(exec, propertyNames, mode);
 }
 
 }
 
-bool DebuggerActivation::getPropertyAttributes(JSC::ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
+bool DebuggerActivation::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return m_activation->getPropertyAttributes(exec, propertyName, attributes);
+    return m_activation->getOwnPropertyDescriptor(exec, propertyName, descriptor);
 }
 
 }
 
-void DebuggerActivation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+void DebuggerActivation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
 {
 {
-    m_activation->defineGetter(exec, propertyName, getterFunction);
+    m_activation->defineGetter(exec, propertyName, getterFunction, attributes);
 }
 
 }
 
-void DebuggerActivation::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
+void DebuggerActivation::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
 {
 {
-    m_activation->defineSetter(exec, propertyName, setterFunction);
+    m_activation->defineSetter(exec, propertyName, setterFunction, attributes);
 }
 
 JSValue DebuggerActivation::lookupGetter(ExecState* exec, const Identifier& propertyName)
 }
 
 JSValue DebuggerActivation::lookupGetter(ExecState* exec, const Identifier& propertyName)
index 9e1f9f52dd379b7cede9a27f800ec93b52f5c89e..392701741ba764b3f44392da99c7006dcc5c4c5d 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,24 +36,27 @@ namespace JSC {
     public:
         DebuggerActivation(JSObject*);
 
     public:
         DebuggerActivation(JSObject*);
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
         virtual UString className() const;
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
         virtual UString className() const;
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
-        virtual void getPropertyNames(ExecState*, PropertyNameArray&);
-        virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
-        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
-        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
+        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes);
+        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes);
         virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
         virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
 
         static PassRefPtr<Structure> createStructure(JSValue prototype) 
         {
         virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
         virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
 
         static PassRefPtr<Structure> createStructure(JSValue prototype) 
         {
-            return Structure::create(prototype, TypeInfo(ObjectType)); 
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
         }
 
         }
 
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | JSObject::StructureFlags;
+
     private:
         JSActivation* m_activation;
     };
     private:
         JSActivation* m_activation;
     };
index cd8702bc44bed163b0ed404b3bea909d5abe7947..a3299d432a0afc79949c82f122be221802b7ef1f 100644 (file)
@@ -41,21 +41,27 @@ const UString* DebuggerCallFrame::functionName() const
     if (!m_callFrame->codeBlock())
         return 0;
 
     if (!m_callFrame->codeBlock())
         return 0;
 
-    JSFunction* function = static_cast<JSFunction*>(m_callFrame->callee());
+    if (!m_callFrame->callee())
+        return 0;
+
+    JSFunction* function = asFunction(m_callFrame->callee());
     if (!function)
         return 0;
     if (!function)
         return 0;
-    return &function->name(&m_callFrame->globalData());
+    return &function->name(m_callFrame);
 }
     
 UString DebuggerCallFrame::calculatedFunctionName() const
 {
     if (!m_callFrame->codeBlock())
         return 0;
 }
     
 UString DebuggerCallFrame::calculatedFunctionName() const
 {
     if (!m_callFrame->codeBlock())
         return 0;
-    
-    JSFunction* function = static_cast<JSFunction*>(m_callFrame->callee());
+
+    if (!m_callFrame->callee())
+        return UString();
+
+    JSFunction* function = asFunction(m_callFrame->callee());
     if (!function)
         return 0;
     if (!function)
         return 0;
-    return function->calculatedDisplayName(&m_callFrame->globalData());
+    return function->calculatedDisplayName(m_callFrame);
 }
 
 DebuggerCallFrame::Type DebuggerCallFrame::type() const
 }
 
 DebuggerCallFrame::Type DebuggerCallFrame::type() const
@@ -79,14 +85,12 @@ JSValue DebuggerCallFrame::evaluate(const UString& script, JSValue& exception) c
     if (!m_callFrame->codeBlock())
         return JSValue();
 
     if (!m_callFrame->codeBlock())
         return JSValue();
 
-    int errLine;
-    UString errMsg;
-    SourceCode source = makeSource(script);
-    RefPtr<EvalNode> evalNode = m_callFrame->scopeChain()->globalData->parser->parse<EvalNode>(m_callFrame, m_callFrame->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-    if (!evalNode)
-        return Error::create(m_callFrame, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
+    RefPtr<EvalExecutable> eval = EvalExecutable::create(m_callFrame, makeSource(script));
+    JSObject* error = eval->compile(m_callFrame, m_callFrame->scopeChain());
+    if (error)
+        return error;
 
 
-    return m_callFrame->scopeChain()->globalData->interpreter->execute(evalNode.get(), m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception);
+    return m_callFrame->scopeChain()->globalData->interpreter->execute(eval.get(), m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index f48f4f4cabd159b6cb8424e1fd02e1af1d140f4a..eb48a03d67a55ac1ee249fc251b244c2ba245e5f 100644 (file)
 #include "Interpreter.h"
 
 namespace JSC {
 #include "Interpreter.h"
 
 namespace JSC {
-    class CachedCall : Noncopyable {
+    class CachedCall : public Noncopyable {
     public:
         CachedCall(CallFrame* callFrame, JSFunction* function, int argCount, JSValue* exception)
             : m_valid(false)
             , m_interpreter(callFrame->interpreter())
             , m_exception(exception)
     public:
         CachedCall(CallFrame* callFrame, JSFunction* function, int argCount, JSValue* exception)
             : m_valid(false)
             , m_interpreter(callFrame->interpreter())
             , m_exception(exception)
-            , m_globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : function->scope().node()->globalObject())
+            , m_globalObjectScope(callFrame, function->scope().globalObject())
         {
         {
-            m_closure = m_interpreter->prepareForRepeatCall(function->body(), callFrame, function, argCount, function->scope().node(), exception);
+            ASSERT(!function->isHostFunction());
+            m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argCount, function->scope().node(), exception);
             m_valid = !*exception;
         }
         
             m_valid = !*exception;
         }
         
@@ -51,7 +52,14 @@ namespace JSC {
         }
         void setThis(JSValue v) { m_closure.setArgument(0, v); }
         void setArgument(int n, JSValue v) { m_closure.setArgument(n + 1, v); }
         }
         void setThis(JSValue v) { m_closure.setArgument(0, v); }
         void setArgument(int n, JSValue v) { m_closure.setArgument(n + 1, v); }
-        CallFrame* newCallFrame() { return m_closure.newCallFrame; }
+
+        CallFrame* newCallFrame(ExecState* exec)
+        {
+            CallFrame* callFrame = m_closure.newCallFrame;
+            callFrame->setScopeChain(exec->scopeChain());
+            return callFrame;
+        }
+
         ~CachedCall()
         {
             if (m_valid)
         ~CachedCall()
         {
             if (m_valid)
index 8126d74aa341814fa57ef621ade07d34a92659c9..e3ea689165a8f5704a1cd74062932e65afc82283 100644 (file)
@@ -39,7 +39,11 @@ namespace JSC  {
     public:
         JSFunction* callee() const { return this[RegisterFile::Callee].function(); }
         CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
     public:
         JSFunction* callee() const { return this[RegisterFile::Callee].function(); }
         CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
-        ScopeChainNode* scopeChain() const { return this[RegisterFile::ScopeChain].Register::scopeChain(); }
+        ScopeChainNode* scopeChain() const
+        {
+            ASSERT(this[RegisterFile::ScopeChain].Register::scopeChain());
+            return this[RegisterFile::ScopeChain].Register::scopeChain();
+        }
         int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
 
         JSValue thisValue();
         int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
 
         JSValue thisValue();
@@ -51,14 +55,14 @@ namespace JSC  {
         // Differs from dynamicGlobalObject() during function calls across web browser frames.
         JSGlobalObject* lexicalGlobalObject() const
         {
         // Differs from dynamicGlobalObject() during function calls across web browser frames.
         JSGlobalObject* lexicalGlobalObject() const
         {
-            return scopeChain()->globalObject();
+            return scopeChain()->globalObject;
         }
 
         // Differs from lexicalGlobalObject because this will have DOM window shell rather than
         // the actual DOM window, which can't be "this" for security reasons.
         JSObject* globalThisValue() const
         {
         }
 
         // Differs from lexicalGlobalObject because this will have DOM window shell rather than
         // the actual DOM window, which can't be "this" for security reasons.
         JSObject* globalThisValue() const
         {
-            return scopeChain()->globalThisObject();
+            return scopeChain()->globalThis;
         }
 
         // FIXME: Elsewhere, we use JSGlobalData* rather than JSGlobalData&.
         }
 
         // FIXME: Elsewhere, we use JSGlobalData* rather than JSGlobalData&.
@@ -66,6 +70,7 @@ namespace JSC  {
         // or a pointer everywhere.
         JSGlobalData& globalData() const
         {
         // or a pointer everywhere.
         JSGlobalData& globalData() const
         {
+            ASSERT(scopeChain()->globalData);
             return *scopeChain()->globalData;
         }
 
             return *scopeChain()->globalData;
         }
 
index 9085327a8273157003aa6d2daa89136b5c89a46f..a301060d26b56d3aefaa3cad8e378a0c085013c0 100644 (file)
@@ -32,7 +32,7 @@ struct CallFrameClosure {
     CallFrame* oldCallFrame;
     CallFrame* newCallFrame;
     JSFunction* function;
     CallFrame* oldCallFrame;
     CallFrame* newCallFrame;
     JSFunction* function;
-    FunctionBodyNode* functionBody;
+    FunctionExecutable* functionExecutable;
     JSGlobalData* globalData;
     Register* oldEnd;
     ScopeChainNode* scopeChain;
     JSGlobalData* globalData;
     Register* oldEnd;
     ScopeChainNode* scopeChain;
index a9e00995a81ce2441351d95cb6af845277cfca50..2498d6978f3ec2f3b9d0119045827c0886283bd5 100644 (file)
@@ -58,6 +58,7 @@
 #include "RegExpPrototype.h"
 #include "Register.h"
 #include "SamplingTool.h"
 #include "RegExpPrototype.h"
 #include "Register.h"
 #include "SamplingTool.h"
+#include <limits.h>
 #include <stdio.h>
 #include <wtf/Threading.h>
 
 #include <stdio.h>
 #include <wtf/Threading.h>
 
@@ -90,8 +91,8 @@ static int depth(CodeBlock* codeBlock, ScopeChain& sc)
 #if USE(INTERPRETER)
 NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
 {
 #if USE(INTERPRETER)
 NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
 {
-    int dst = (vPC + 1)->u.operand;
-    int property = (vPC + 2)->u.operand;
+    int dst = vPC[1].u.operand;
+    int property = vPC[2].u.operand;
 
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     ScopeChainIterator iter = scopeChain->begin();
 
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     ScopeChainIterator iter = scopeChain->begin();
@@ -120,9 +121,9 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP
 {
     CodeBlock* codeBlock = callFrame->codeBlock();
 
 {
     CodeBlock* codeBlock = callFrame->codeBlock();
 
-    int dst = (vPC + 1)->u.operand;
-    int property = (vPC + 2)->u.operand;
-    int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain();
+    int dst = vPC[1].u.operand;
+    int property = vPC[2].u.operand;
+    int skip = vPC[3].u.operand + codeBlock->needsFullScopeChain();
 
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     ScopeChainIterator iter = scopeChain->begin();
 
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     ScopeChainIterator iter = scopeChain->begin();
@@ -151,12 +152,12 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP
 
 NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
 {
 
 NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
 {
-    int dst = (vPC + 1)->u.operand;
-    JSGlobalObject* globalObject = static_cast<JSGlobalObject*>((vPC + 2)->u.jsCell);
+    int dst = vPC[1].u.operand;
+    JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(vPC[2].u.jsCell);
     ASSERT(globalObject->isGlobalObject());
     ASSERT(globalObject->isGlobalObject());
-    int property = (vPC + 3)->u.operand;
-    Structure* structure = (vPC + 4)->u.structure;
-    int offset = (vPC + 5)->u.operand;
+    int property = vPC[3].u.operand;
+    Structure* structure = vPC[4].u.structure;
+    int offset = vPC[5].u.operand;
 
     if (structure == globalObject->structure()) {
         callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset));
 
     if (structure == globalObject->structure()) {
         callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset));
@@ -191,16 +192,16 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction*
 
 NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC)
 {
 
 NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC)
 {
-    int dst = (vPC + 1)->u.operand;
-    int property = (vPC + 2)->u.operand;
+    int dst = vPC[1].u.operand;
+    int property = vPC[2].u.operand;
     callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
 }
 
 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
 {
     callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
 }
 
 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
 {
-    int baseDst = (vPC + 1)->u.operand;
-    int propDst = (vPC + 2)->u.operand;
-    int property = (vPC + 3)->u.operand;
+    int baseDst = vPC[1].u.operand;
+    int propDst = vPC[2].u.operand;
+    int property = vPC[3].u.operand;
 
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     ScopeChainIterator iter = scopeChain->begin();
 
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     ScopeChainIterator iter = scopeChain->begin();
@@ -232,51 +233,6 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst
     return false;
 }
 
     return false;
 }
 
-NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
-{
-    int baseDst = (vPC + 1)->u.operand;
-    int funcDst = (vPC + 2)->u.operand;
-    int property = (vPC + 3)->u.operand;
-
-    ScopeChainNode* scopeChain = callFrame->scopeChain();
-    ScopeChainIterator iter = scopeChain->begin();
-    ScopeChainIterator end = scopeChain->end();
-
-    // FIXME: add scopeDepthIsZero optimization
-
-    ASSERT(iter != end);
-
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    Identifier& ident = codeBlock->identifier(property);
-    JSObject* base;
-    do {
-        base = *iter;
-        PropertySlot slot(base);
-        if (base->getPropertySlot(callFrame, ident, slot)) {            
-            // ECMA 11.2.3 says that if we hit an activation the this value should be null.
-            // However, section 10.2.3 says that in the case where the value provided
-            // by the caller is null, the global object should be used. It also says
-            // that the section does not apply to internal functions, but for simplicity
-            // of implementation we use the global object anyway here. This guarantees
-            // that in host objects you always get a valid object for this.
-            // We also handle wrapper substitution for the global object at the same time.
-            JSObject* thisObj = base->toThisObject(callFrame);
-            JSValue result = slot.getValue(callFrame, ident);
-            exceptionValue = callFrame->globalData().exception;
-            if (exceptionValue)
-                return false;
-
-            callFrame->r(baseDst) = JSValue(thisObj);
-            callFrame->r(funcDst) = JSValue(result);
-            return true;
-        }
-        ++iter;
-    } while (iter != end);
-
-    exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
-    return false;
-}
-
 #endif // USE(INTERPRETER)
 
 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
 #endif // USE(INTERPRETER)
 
 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
@@ -344,26 +300,25 @@ NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* r
     if (!program.isString())
         return program;
 
     if (!program.isString())
         return program;
 
-    UString programSource = asString(program)->value();
+    UString programSource = asString(program)->value(callFrame);
 
     LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
     if (JSValue parsedObject = preparser.tryLiteralParse())
         return parsedObject;
 
     LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
     if (JSValue parsedObject = preparser.tryLiteralParse())
         return parsedObject;
-    
-    
+
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     CodeBlock* codeBlock = callFrame->codeBlock();
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     CodeBlock* codeBlock = callFrame->codeBlock();
-    RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
+    RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
 
     JSValue result = jsUndefined();
 
     JSValue result = jsUndefined();
-    if (evalNode)
-        result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
+    if (eval)
+        result = callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
 
     return result;
 }
 
 Interpreter::Interpreter()
 
     return result;
 }
 
 Interpreter::Interpreter()
-    : m_sampler(0)
+    : m_sampleEntryDepth(0)
     , m_reentryDepth(0)
 {
 #if HAVE(COMPUTED_GOTO)
     , m_reentryDepth(0)
 {
 #if HAVE(COMPUTED_GOTO)
@@ -372,6 +327,10 @@ Interpreter::Interpreter()
     for (int i = 0; i < numOpcodeIDs; ++i)
         m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
 #endif // HAVE(COMPUTED_GOTO)
     for (int i = 0; i < numOpcodeIDs; ++i)
         m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
 #endif // HAVE(COMPUTED_GOTO)
+
+#if ENABLE(OPCODE_SAMPLING)
+    enableSampler();
+#endif
 }
 
 #ifndef NDEBUG
 }
 
 #ifndef NDEBUG
@@ -390,7 +349,7 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
     printf("-----------------------------------------------------------------------------\n");
 
     CodeBlock* codeBlock = callFrame->codeBlock();
     printf("-----------------------------------------------------------------------------\n");
 
     CodeBlock* codeBlock = callFrame->codeBlock();
-    RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->interpreter->registerFile();
+    RegisterFile* registerFile = &callFrame->scopeChain()->globalObject->globalData()->interpreter->registerFile();
     const Register* it;
     const Register* end;
     JSValue v;
     const Register* it;
     const Register* end;
     JSValue v;
@@ -494,21 +453,21 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex
     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
         if (callFrame->callee())
     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
         if (callFrame->callee())
-            debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine());
+            debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
         else
         else
-            debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine());
+            debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
     }
 
     if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
         if (callFrame->callee())
             profiler->didExecute(callFrame, callFrame->callee());
         else
     }
 
     if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
         if (callFrame->callee())
             profiler->didExecute(callFrame, callFrame->callee());
         else
-            profiler->didExecute(callFrame, codeBlock->ownerNode()->sourceURL(), codeBlock->ownerNode()->lineNo());
+            profiler->didExecute(callFrame, codeBlock->ownerExecutable()->sourceURL(), codeBlock->ownerExecutable()->lineNo());
     }
 
     // If this call frame created an activation or an 'arguments' object, tear it off.
     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
     }
 
     // If this call frame created an activation or an 'arguments' object, tear it off.
     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
-        while (!scopeChain->object->isObject(&JSActivation::info))
+        while (!scopeChain->object->inherits(&JSActivation::info))
             scopeChain = scopeChain->pop();
         static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments());
     } else if (Arguments* arguments = callFrame->optionalCalleeArguments()) {
             scopeChain = scopeChain->pop();
         static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments());
     } else if (Arguments* arguments = callFrame->optionalCalleeArguments()) {
@@ -559,8 +518,8 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
                     exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete);
                 } else
                     exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete);
                     exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete);
                 } else
                     exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete);
-                exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerNode()->sourceID()), ReadOnly | DontDelete);
-                exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerNode()->sourceURL()), ReadOnly | DontDelete);
+                exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerExecutable()->sourceID()), ReadOnly | DontDelete);
+                exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerExecutable()->sourceURL()), ReadOnly | DontDelete);
             }
             
             if (exception->isWatchdogException()) {
             }
             
             if (exception->isWatchdogException()) {
@@ -574,7 +533,8 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
 
     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
 
     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
-        debugger->exception(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset));
+        bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
+        debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset), hasHandler);
     }
 
     // If we throw in the middle of a call instruction, we need to notify
     }
 
     // If we throw in the middle of a call instruction, we need to notify
@@ -584,7 +544,7 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
 #if !ENABLE(JIT)
         if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
             profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 2].u.operand).jsValue());
 #if !ENABLE(JIT)
         if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
             profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 2].u.operand).jsValue());
-        else if (codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
+        else if (codeBlock->instructions().size() > (bytecodeOffset + 8) && codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
             profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 10].u.operand).jsValue());
 #else
         int functionRegisterIndex;
             profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 10].u.operand).jsValue());
 #else
         int functionRegisterIndex;
@@ -614,7 +574,7 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
     return handler;
 }
 
     return handler;
 }
 
-JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception)
+JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception)
 {
     ASSERT(!scopeChain->globalData->exception);
 
 {
     ASSERT(!scopeChain->globalData->exception);
 
@@ -625,7 +585,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco
         }
     }
 
         }
     }
 
-    CodeBlock* codeBlock = &programNode->bytecode(scopeChain);
+    CodeBlock* codeBlock = &program->bytecode(callFrame, scopeChain);
 
     Register* oldEnd = m_registerFile.end();
     Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
 
     Register* oldEnd = m_registerFile.end();
     Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
@@ -634,7 +594,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco
         return jsNull();
     }
 
         return jsNull();
     }
 
-    DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject());
+    DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
 
     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
     JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
 
     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
     JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
@@ -649,15 +609,15 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo());
+        (*profiler)->willExecute(newCallFrame, program->sourceURL(), program->lineNo());
 
     JSValue result;
     {
 
     JSValue result;
     {
-        SamplingTool::CallRecord callRecord(m_sampler);
+        SamplingTool::CallRecord callRecord(m_sampler.get());
 
         m_reentryDepth++;
 #if ENABLE(JIT)
 
         m_reentryDepth++;
 #if ENABLE(JIT)
-        result = programNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+        result = program->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
 #else
         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
 #endif
 #else
         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
 #endif
@@ -665,7 +625,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco
     }
 
     if (*profiler)
     }
 
     if (*profiler)
-        (*profiler)->didExecute(callFrame, programNode->sourceURL(), programNode->lineNo());
+        (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
 
     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
         lastGlobalObject->copyGlobalsTo(m_registerFile);
 
     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
         lastGlobalObject->copyGlobalsTo(m_registerFile);
@@ -675,7 +635,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco
     return result;
 }
 
     return result;
 }
 
-JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception)
+JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception)
 {
     ASSERT(!scopeChain->globalData->exception);
 
 {
     ASSERT(!scopeChain->globalData->exception);
 
@@ -694,7 +654,7 @@ JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* call
         return jsNull();
     }
 
         return jsNull();
     }
 
-    DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
+    DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
 
     CallFrame* newCallFrame = CallFrame::create(oldEnd);
     size_t dst = 0;
 
     CallFrame* newCallFrame = CallFrame::create(oldEnd);
     size_t dst = 0;
@@ -703,7 +663,7 @@ JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* call
     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
         newCallFrame->r(++dst) = *it;
 
     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
         newCallFrame->r(++dst) = *it;
 
-    CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain);
+    CodeBlock* codeBlock = &functionExecutable->bytecode(callFrame, scopeChain);
     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
     if (UNLIKELY(!newCallFrame)) {
         *exception = createStackOverflowError(callFrame);
     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
     if (UNLIKELY(!newCallFrame)) {
         *exception = createStackOverflowError(callFrame);
@@ -719,11 +679,11 @@ JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* call
 
     JSValue result;
     {
 
     JSValue result;
     {
-        SamplingTool::CallRecord callRecord(m_sampler);
+        SamplingTool::CallRecord callRecord(m_sampler.get());
 
         m_reentryDepth++;
 #if ENABLE(JIT)
 
         m_reentryDepth++;
 #if ENABLE(JIT)
-        result = functionBodyNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+        result = functionExecutable->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
 #else
         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
 #endif
 #else
         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
 #endif
@@ -737,7 +697,7 @@ JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* call
     return result;
 }
 
     return result;
 }
 
-CallFrameClosure Interpreter::prepareForRepeatCall(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception)
+CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception)
 {
     ASSERT(!scopeChain->globalData->exception);
     
 {
     ASSERT(!scopeChain->globalData->exception);
     
@@ -761,7 +721,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionBodyNode* functionBod
     for (int i = 0; i < argc; ++i)
         newCallFrame->r(++dst) = jsUndefined();
     
     for (int i = 0; i < argc; ++i)
         newCallFrame->r(++dst) = jsUndefined();
     
-    CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain);
+    CodeBlock* codeBlock = &FunctionExecutable->bytecode(callFrame, scopeChain);
     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
     if (UNLIKELY(!newCallFrame)) {
         *exception = createStackOverflowError(callFrame);
     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
     if (UNLIKELY(!newCallFrame)) {
         *exception = createStackOverflowError(callFrame);
@@ -771,10 +731,10 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionBodyNode* functionBod
     // a 0 codeBlock indicates a built-in caller
     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
 #if ENABLE(JIT)
     // a 0 codeBlock indicates a built-in caller
     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
 #if ENABLE(JIT)
-    functionBodyNode->jitCode(scopeChain);
+    FunctionExecutable->jitCode(newCallFrame, scopeChain);
 #endif
 
 #endif
 
-    CallFrameClosure result = { callFrame, newCallFrame, function, functionBodyNode, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
+    CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
     return result;
 }
 
     return result;
 }
 
@@ -787,11 +747,11 @@ JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception)
     
     JSValue result;
     {
     
     JSValue result;
     {
-        SamplingTool::CallRecord callRecord(m_sampler);
+        SamplingTool::CallRecord callRecord(m_sampler.get());
         
         m_reentryDepth++;
 #if ENABLE(JIT)
         
         m_reentryDepth++;
 #if ENABLE(JIT)
-        result = closure.functionBody->generatedJITCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
+        result = closure.functionExecutable->generatedJITCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
 #else
         result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
 #endif
 #else
         result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
 #endif
@@ -808,12 +768,12 @@ void Interpreter::endRepeatCall(CallFrameClosure& closure)
     m_registerFile.shrink(closure.oldEnd);
 }
 
     m_registerFile.shrink(closure.oldEnd);
 }
 
-JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception)
+JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception)
 {
 {
-    return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNode->bytecode(scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
+    return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->bytecode(callFrame, scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
 }
 
 }
 
-JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
+JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
 {
     ASSERT(!scopeChain->globalData->exception);
 
 {
     ASSERT(!scopeChain->globalData->exception);
 
@@ -824,9 +784,9 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject*
         }
     }
 
         }
     }
 
-    DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
+    DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
 
 
-    EvalCodeBlock* codeBlock = &evalNode->bytecode(scopeChain);
+    EvalCodeBlock* codeBlock = &eval->bytecode(callFrame, scopeChain);
 
     JSVariableObject* variableObject;
     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
 
     JSVariableObject* variableObject;
     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
@@ -841,21 +801,20 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject*
 
         BatchedTransitionOptimizer optimizer(variableObject);
 
 
         BatchedTransitionOptimizer optimizer(variableObject);
 
-        const DeclarationStacks::VarStack& varStack = codeBlock->ownerNode()->varStack();
-        DeclarationStacks::VarStack::const_iterator varStackEnd = varStack.end();
-        for (DeclarationStacks::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
-            const Identifier& ident = (*it).first;
+        unsigned numVariables = codeBlock->numVariables();
+        for (unsigned i = 0; i < numVariables; ++i) {
+            const Identifier& ident = codeBlock->variable(i);
             if (!variableObject->hasProperty(callFrame, ident)) {
                 PutPropertySlot slot;
                 variableObject->put(callFrame, ident, jsUndefined(), slot);
             }
         }
 
             if (!variableObject->hasProperty(callFrame, ident)) {
                 PutPropertySlot slot;
                 variableObject->put(callFrame, ident, jsUndefined(), slot);
             }
         }
 
-        const DeclarationStacks::FunctionStack& functionStack = codeBlock->ownerNode()->functionStack();
-        DeclarationStacks::FunctionStack::const_iterator functionStackEnd = functionStack.end();
-        for (DeclarationStacks::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) {
+        int numFunctions = codeBlock->numberOfFunctionDecls();
+        for (int i = 0; i < numFunctions; ++i) {
+            FunctionExecutable* function = codeBlock->functionDecl(i);
             PutPropertySlot slot;
             PutPropertySlot slot;
-            variableObject->put(callFrame, (*it)->m_ident, (*it)->makeFunction(callFrame, scopeChain), slot);
+            variableObject->put(callFrame, function->name(), function->make(callFrame, scopeChain), slot);
         }
 
     }
         }
 
     }
@@ -878,15 +837,15 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject*
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->lineNo());
+        (*profiler)->willExecute(newCallFrame, eval->sourceURL(), eval->lineNo());
 
     JSValue result;
     {
 
     JSValue result;
     {
-        SamplingTool::CallRecord callRecord(m_sampler);
+        SamplingTool::CallRecord callRecord(m_sampler.get());
 
         m_reentryDepth++;
 #if ENABLE(JIT)
 
         m_reentryDepth++;
 #if ENABLE(JIT)
-        result = evalNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+        result = eval->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
 #else
         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
 #endif
 #else
         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
 #endif
@@ -894,7 +853,7 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject*
     }
 
     if (*profiler)
     }
 
     if (*profiler)
-        (*profiler)->didExecute(callFrame, evalNode->sourceURL(), evalNode->lineNo());
+        (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
 
     m_registerFile.shrink(oldEnd);
     return result;
 
     m_registerFile.shrink(oldEnd);
     return result;
@@ -908,22 +867,22 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook
 
     switch (debugHookID) {
         case DidEnterCallFrame:
 
     switch (debugHookID) {
         case DidEnterCallFrame:
-            debugger->callEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
+            debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
             return;
         case WillLeaveCallFrame:
             return;
         case WillLeaveCallFrame:
-            debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
+            debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
             return;
         case WillExecuteStatement:
             return;
         case WillExecuteStatement:
-            debugger->atStatement(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
+            debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
             return;
         case WillExecuteProgram:
             return;
         case WillExecuteProgram:
-            debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
+            debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
             return;
         case DidExecuteProgram:
             return;
         case DidExecuteProgram:
-            debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
+            debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
             return;
         case DidReachBreakpoint:
             return;
         case DidReachBreakpoint:
-            debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
+            debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
             return;
     }
 }
             return;
     }
 }
@@ -931,10 +890,10 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook
 #if USE(INTERPRETER)
 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
 {
 #if USE(INTERPRETER)
 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
 {
-    int dst = (++vPC)->u.operand;
+    int dst = vPC[1].u.operand;
     CodeBlock* codeBlock = callFrame->codeBlock();
     CodeBlock* codeBlock = callFrame->codeBlock();
-    Identifier& property = codeBlock->identifier((++vPC)->u.operand);
-    JSValue value = callFrame->r((++vPC)->u.operand).jsValue();
+    Identifier& property = codeBlock->identifier(vPC[2].u.operand);
+    JSValue value = callFrame->r(vPC[3].u.operand).jsValue();
     JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
     callFrame->r(dst) = JSValue(scope);
 
     JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
     callFrame->r(dst) = JSValue(scope);
 
@@ -986,22 +945,20 @@ NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock*
         return;
     }
 
         return;
     }
 
-    StructureChain* protoChain = structure->prototypeChain(callFrame);
-    if (!protoChain->isCacheable()) {
-        vPC[0] = getOpcode(op_put_by_id_generic);
-        return;
-    }
-
     // Structure transition, cache transition info
     if (slot.type() == PutPropertySlot::NewProperty) {
         if (structure->isDictionary()) {
             vPC[0] = getOpcode(op_put_by_id_generic);
             return;
         }
     // Structure transition, cache transition info
     if (slot.type() == PutPropertySlot::NewProperty) {
         if (structure->isDictionary()) {
             vPC[0] = getOpcode(op_put_by_id_generic);
             return;
         }
+
+        // put_by_id_transition checks the prototype chain for setters.
+        normalizePrototypeChain(callFrame, baseCell);
+
         vPC[0] = getOpcode(op_put_by_id_transition);
         vPC[4] = structure->previousID();
         vPC[5] = structure;
         vPC[0] = getOpcode(op_put_by_id_transition);
         vPC[4] = structure->previousID();
         vPC[5] = structure;
-        vPC[6] = protoChain;
+        vPC[6] = structure->prototypeChain(callFrame);
         vPC[7] = slot.cachedOffset();
         codeBlock->refStructures(vPC);
         return;
         vPC[7] = slot.cachedOffset();
         codeBlock->refStructures(vPC);
         return;
@@ -1114,15 +1071,9 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
         return;
     }
 
         return;
     }
 
-    StructureChain* protoChain = structure->prototypeChain(callFrame);
-    if (!protoChain->isCacheable()) {
-        vPC[0] = getOpcode(op_get_by_id_generic);
-        return;
-    }
-
     vPC[0] = getOpcode(op_get_by_id_chain);
     vPC[4] = structure;
     vPC[0] = getOpcode(op_get_by_id_chain);
     vPC[4] = structure;
-    vPC[5] = protoChain;
+    vPC[5] = structure->prototypeChain(callFrame);
     vPC[6] = count;
     vPC[7] = offset;
     codeBlock->refStructures(vPC);
     vPC[6] = count;
     vPC[7] = offset;
     codeBlock->refStructures(vPC);
@@ -1224,10 +1175,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Constructs a new empty Object instance using the original
            constructor, and puts the result in register dst.
         */
            Constructs a new empty Object instance using the original
            constructor, and puts the result in register dst.
         */
-        int dst = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
         callFrame->r(dst) = JSValue(constructEmptyObject(callFrame));
 
         callFrame->r(dst) = JSValue(constructEmptyObject(callFrame));
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_new_object);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_new_array) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_new_array) {
@@ -1238,13 +1189,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            The array will contain argCount elements with values
            taken from registers starting at register firstArg.
         */
            The array will contain argCount elements with values
            taken from registers starting at register firstArg.
         */
-        int dst = (++vPC)->u.operand;
-        int firstArg = (++vPC)->u.operand;
-        int argCount = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int firstArg = vPC[2].u.operand;
+        int argCount = vPC[3].u.operand;
         ArgList args(callFrame->registers() + firstArg, argCount);
         callFrame->r(dst) = JSValue(constructArray(callFrame, args));
 
         ArgList args(callFrame->registers() + firstArg, argCount);
         callFrame->r(dst) = JSValue(constructArray(callFrame, args));
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_new_array);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_new_regexp) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_new_regexp) {
@@ -1254,11 +1205,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            constructor from regexp regExp, and puts the result in
            register dst.
         */
            constructor from regexp regExp, and puts the result in
            register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int regExp = (++vPC)->u.operand;
-        callFrame->r(dst) = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
+        int dst = vPC[1].u.operand;
+        int regExp = vPC[2].u.operand;
+        callFrame->r(dst) = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
 
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_new_regexp);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_mov) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_mov) {
@@ -1266,11 +1217,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
            Copies register src to register dst.
         */
 
            Copies register src to register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
         callFrame->r(dst) = callFrame->r(src);
 
         callFrame->r(dst) = callFrame->r(src);
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_mov);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_eq) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_eq) {
@@ -1280,9 +1231,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            as with the ECMAScript '==' operator, and puts the result
            as a boolean in register dst.
         */
            as with the ECMAScript '==' operator, and puts the result
            as a boolean in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32())
             callFrame->r(dst) = jsBoolean(src1.asInt32() == src2.asInt32());
         else {
         if (src1.isInt32() && src2.isInt32())
             callFrame->r(dst) = jsBoolean(src1.asInt32() == src2.asInt32());
         else {
@@ -1291,7 +1242,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_eq);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_eq_null) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_eq_null) {
@@ -1300,17 +1251,17 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Checks whether register src is null, as with the ECMAScript '!='
            operator, and puts the result as a boolean in register dst.
         */
            Checks whether register src is null, as with the ECMAScript '!='
            operator, and puts the result as a boolean in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
 
         if (src.isUndefinedOrNull()) {
             callFrame->r(dst) = jsBoolean(true);
 
         if (src.isUndefinedOrNull()) {
             callFrame->r(dst) = jsBoolean(true);
-            ++vPC;
+            vPC += OPCODE_LENGTH(op_eq_null);
             NEXT_INSTRUCTION();
         }
         
         callFrame->r(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
             NEXT_INSTRUCTION();
         }
         
         callFrame->r(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_eq_null);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_neq) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_neq) {
@@ -1320,9 +1271,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            equal, as with the ECMAScript '!=' operator, and puts the
            result as a boolean in register dst.
         */
            equal, as with the ECMAScript '!=' operator, and puts the
            result as a boolean in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32())
             callFrame->r(dst) = jsBoolean(src1.asInt32() != src2.asInt32());
         else {
         if (src1.isInt32() && src2.isInt32())
             callFrame->r(dst) = jsBoolean(src1.asInt32() != src2.asInt32());
         else {
@@ -1331,7 +1282,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_neq);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_neq_null) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_neq_null) {
@@ -1340,17 +1291,17 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Checks whether register src is not null, as with the ECMAScript '!='
            operator, and puts the result as a boolean in register dst.
         */
            Checks whether register src is not null, as with the ECMAScript '!='
            operator, and puts the result as a boolean in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
 
         if (src.isUndefinedOrNull()) {
             callFrame->r(dst) = jsBoolean(false);
 
         if (src.isUndefinedOrNull()) {
             callFrame->r(dst) = jsBoolean(false);
-            ++vPC;
+            vPC += OPCODE_LENGTH(op_neq_null);
             NEXT_INSTRUCTION();
         }
         
         callFrame->r(dst) = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined());
             NEXT_INSTRUCTION();
         }
         
         callFrame->r(dst) = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined());
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_neq_null);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_stricteq) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_stricteq) {
@@ -1360,12 +1311,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            equal, as with the ECMAScript '===' operator, and puts the
            result as a boolean in register dst.
         */
            equal, as with the ECMAScript '===' operator, and puts the
            result as a boolean in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
-        callFrame->r(dst) = jsBoolean(JSValue::strictEqual(src1, src2));
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
+        callFrame->r(dst) = jsBoolean(JSValue::strictEqual(callFrame, src1, src2));
 
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_stricteq);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_nstricteq) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_nstricteq) {
@@ -1375,12 +1326,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            strictly equal, as with the ECMAScript '!==' operator, and
            puts the result as a boolean in register dst.
         */
            strictly equal, as with the ECMAScript '!==' operator, and
            puts the result as a boolean in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
-        callFrame->r(dst) = jsBoolean(!JSValue::strictEqual(src1, src2));
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
+        callFrame->r(dst) = jsBoolean(!JSValue::strictEqual(callFrame, src1, src2));
 
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_nstricteq);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_less) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_less) {
@@ -1390,14 +1341,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            with the ECMAScript '<' operator, and puts the result as
            a boolean in register dst.
         */
            with the ECMAScript '<' operator, and puts the result as
            a boolean in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         JSValue result = jsBoolean(jsLess(callFrame, src1, src2));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
         JSValue result = jsBoolean(jsLess(callFrame, src1, src2));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_less);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_lesseq) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_lesseq) {
@@ -1407,14 +1358,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            register src2, as with the ECMAScript '<=' operator, and
            puts the result as a boolean in register dst.
         */
            register src2, as with the ECMAScript '<=' operator, and
            puts the result as a boolean in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
         JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_lesseq);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_pre_inc) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_pre_inc) {
@@ -1423,7 +1374,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Converts register srcDst to number, adds one, and puts the result
            back in register srcDst.
         */
            Converts register srcDst to number, adds one, and puts the result
            back in register srcDst.
         */
-        int srcDst = (++vPC)->u.operand;
+        int srcDst = vPC[1].u.operand;
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() < INT_MAX)
             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() < INT_MAX)
             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
@@ -1433,7 +1384,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(srcDst) = result;
         }
 
             callFrame->r(srcDst) = result;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_pre_inc);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_pre_dec) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_pre_dec) {
@@ -1442,7 +1393,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Converts register srcDst to number, subtracts one, and puts the result
            back in register srcDst.
         */
            Converts register srcDst to number, subtracts one, and puts the result
            back in register srcDst.
         */
-        int srcDst = (++vPC)->u.operand;
+        int srcDst = vPC[1].u.operand;
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() > INT_MIN)
             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() > INT_MIN)
             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
@@ -1452,7 +1403,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(srcDst) = result;
         }
 
             callFrame->r(srcDst) = result;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_pre_dec);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_post_inc) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_post_inc) {
@@ -1462,8 +1413,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            written to register dst, and the number plus one is written
            back to register srcDst.
         */
            written to register dst, and the number plus one is written
            back to register srcDst.
         */
-        int dst = (++vPC)->u.operand;
-        int srcDst = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int srcDst = vPC[2].u.operand;
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() < INT_MAX) {
             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() < INT_MAX) {
             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
@@ -1475,7 +1426,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = number;
         }
 
             callFrame->r(dst) = number;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_post_inc);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_post_dec) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_post_dec) {
@@ -1485,8 +1436,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            written to register dst, and the number minus one is written
            back to register srcDst.
         */
            written to register dst, and the number minus one is written
            back to register srcDst.
         */
-        int dst = (++vPC)->u.operand;
-        int srcDst = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int srcDst = vPC[2].u.operand;
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() > INT_MIN) {
             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() > INT_MIN) {
             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
@@ -1498,7 +1449,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = number;
         }
 
             callFrame->r(dst) = number;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_post_dec);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_to_jsnumber) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_to_jsnumber) {
@@ -1507,8 +1458,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Converts register src to number, and puts the result
            in register dst.
         */
            Converts register src to number, and puts the result
            in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
 
         JSValue srcVal = callFrame->r(src).jsValue();
 
 
         JSValue srcVal = callFrame->r(src).jsValue();
 
@@ -1520,7 +1471,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_to_jsnumber);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_negate) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_negate) {
@@ -1529,8 +1480,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Converts register src to number, negates it, and puts the
            result in register dst.
         */
            Converts register src to number, negates it, and puts the
            result in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
         if (src.isInt32() && src.asInt32())
             callFrame->r(dst) = jsNumber(callFrame, -src.asInt32());
         else {
         if (src.isInt32() && src.asInt32())
             callFrame->r(dst) = jsNumber(callFrame, -src.asInt32());
         else {
@@ -1539,7 +1490,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_negate);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_add) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_add) {
@@ -1549,17 +1500,17 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            in register dst. (JS add may be string concatenation or
            numeric add, depending on the types of the operands.)
         */
            in register dst. (JS add may be string concatenation or
            numeric add, depending on the types of the operands.)
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
-        if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() & 0xc0000000)) // no overflow
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
+        if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() + src2.asInt32());
         else {
             JSValue result = jsAdd(callFrame, src1, src2);
             CHECK_FOR_EXCEPTION();
             callFrame->r(dst) = result;
         }
             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() + src2.asInt32());
         else {
             JSValue result = jsAdd(callFrame, src1, src2);
             CHECK_FOR_EXCEPTION();
             callFrame->r(dst) = result;
         }
-        vPC += 2;
+        vPC += OPCODE_LENGTH(op_add);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_mul) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_mul) {
@@ -1568,9 +1519,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Multiplies register src1 and register src2 (converted to
            numbers), and puts the product in register dst.
         */
            Multiplies register src1 and register src2 (converted to
            numbers), and puts the product in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow
                 callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() * src2.asInt32());
         else {
         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow
                 callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() * src2.asInt32());
         else {
@@ -1579,7 +1530,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        vPC += 2;
+        vPC += OPCODE_LENGTH(op_mul);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_div) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_div) {
@@ -1589,15 +1540,15 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            register divisor (converted to number), and puts the
            quotient in register dst.
         */
            register divisor (converted to number), and puts the
            quotient in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue dividend = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue divisor = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
 
         JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
 
         JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
-        vPC += 2;
+        vPC += OPCODE_LENGTH(op_div);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_mod) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_mod) {
@@ -1607,15 +1558,15 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            register divisor (converted to number), and puts the
            remainder in register dst.
         */
            register divisor (converted to number), and puts the
            remainder in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue dividend = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue divisor = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
 
         if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) {
             JSValue result = jsNumber(callFrame, dividend.asInt32() % divisor.asInt32());
             ASSERT(result);
             callFrame->r(dst) = result;
 
         if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) {
             JSValue result = jsNumber(callFrame, dividend.asInt32() % divisor.asInt32());
             ASSERT(result);
             callFrame->r(dst) = result;
-            ++vPC;
+            vPC += OPCODE_LENGTH(op_mod);
             NEXT_INSTRUCTION();
         }
 
             NEXT_INSTRUCTION();
         }
 
@@ -1626,7 +1577,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue result = jsNumber(callFrame, fmod(d1, d2));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
         JSValue result = jsNumber(callFrame, fmod(d1, d2));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_mod);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_sub) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_sub) {
@@ -1636,17 +1587,17 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            src1 (converted to number), and puts the difference in
            register dst.
         */
            src1 (converted to number), and puts the difference in
            register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
-        if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() & 0xc0000000)) // no overflow
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
+        if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() - src2.asInt32());
         else {
             JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
             CHECK_FOR_EXCEPTION();
             callFrame->r(dst) = result;
         }
             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() - src2.asInt32());
         else {
             JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
             CHECK_FOR_EXCEPTION();
             callFrame->r(dst) = result;
         }
-        vPC += 2;
+        vPC += OPCODE_LENGTH(op_sub);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_lshift) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_lshift) {
@@ -1656,9 +1607,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            register shift (converted to uint32), and puts the result
            in register dst.
         */
            register shift (converted to uint32), and puts the result
            in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue val = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue shift = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
 
         if (val.isInt32() && shift.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() << (shift.asInt32() & 0x1f));
 
         if (val.isInt32() && shift.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() << (shift.asInt32() & 0x1f));
@@ -1668,7 +1619,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_lshift);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_rshift) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_rshift) {
@@ -1678,9 +1629,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            to int32) by register shift (converted to
            uint32), and puts the result in register dst.
         */
            to int32) by register shift (converted to
            uint32), and puts the result in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue val = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue shift = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
 
         if (val.isInt32() && shift.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
 
         if (val.isInt32() && shift.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
@@ -1690,7 +1641,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_rshift);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_urshift) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_urshift) {
@@ -1700,9 +1651,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            to uint32) by register shift (converted to
            uint32), and puts the result in register dst.
         */
            to uint32) by register shift (converted to
            uint32), and puts the result in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue val = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue shift = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
         if (val.isUInt32() && shift.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
         else {
         if (val.isUInt32() && shift.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
         else {
@@ -1711,7 +1662,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_urshift);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_bitand) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_bitand) {
@@ -1721,9 +1672,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            and register src2 (converted to int32), and puts the result
            in register dst.
         */
            and register src2 (converted to int32), and puts the result
            in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() & src2.asInt32());
         else {
         if (src1.isInt32() && src2.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() & src2.asInt32());
         else {
@@ -1732,7 +1683,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        vPC += 2;
+        vPC += OPCODE_LENGTH(op_bitand);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_bitxor) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_bitxor) {
@@ -1742,9 +1693,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            and register src2 (converted to int32), and puts the result
            in register dst.
         */
            and register src2 (converted to int32), and puts the result
            in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() ^ src2.asInt32());
         else {
         if (src1.isInt32() && src2.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() ^ src2.asInt32());
         else {
@@ -1753,7 +1704,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        vPC += 2;
+        vPC += OPCODE_LENGTH(op_bitxor);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_bitor) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_bitor) {
@@ -1763,9 +1714,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            and register src2 (converted to int32), and puts the
            result in register dst.
         */
            and register src2 (converted to int32), and puts the
            result in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() | src2.asInt32());
         else {
         if (src1.isInt32() && src2.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() | src2.asInt32());
         else {
@@ -1774,7 +1725,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = result;
         }
 
             callFrame->r(dst) = result;
         }
 
-        vPC += 2;
+        vPC += OPCODE_LENGTH(op_bitor);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_bitnot) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_bitnot) {
@@ -1783,8 +1734,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Computes bitwise NOT of register src1 (converted to int32),
            and puts the result in register dst.
         */
            Computes bitwise NOT of register src1 (converted to int32),
            and puts the result in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        JSValue src = callFrame->r((++vPC)->u.operand).jsValue();
+        int dst = vPC[1].u.operand;
+        JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
         if (src.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, ~src.asInt32());
         else {
         if (src.isInt32())
             callFrame->r(dst) = jsNumber(callFrame, ~src.asInt32());
         else {
@@ -1792,7 +1743,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             CHECK_FOR_EXCEPTION();
             callFrame->r(dst) = result;
         }
             CHECK_FOR_EXCEPTION();
             callFrame->r(dst) = result;
         }
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_bitnot);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_not) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_not) {
@@ -1801,13 +1752,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Computes logical NOT of register src (converted to
            boolean), and puts the result in register dst.
         */
            Computes logical NOT of register src (converted to
            boolean), and puts the result in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
         JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
         JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_not);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_instanceof) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_instanceof) {
@@ -1837,7 +1788,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = jsBoolean(result);
 
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = jsBoolean(result);
 
-        vPC += 5;
+        vPC += OPCODE_LENGTH(op_instanceof);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_typeof) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_typeof) {
@@ -1846,11 +1797,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Determines the type string for src according to ECMAScript
            rules, and puts the result in register dst.
         */
            Determines the type string for src according to ECMAScript
            rules, and puts the result in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
         callFrame->r(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue()));
 
         callFrame->r(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue()));
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_typeof);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_undefined) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_undefined) {
@@ -1860,12 +1811,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            the ECMAScript rules is "undefined", and puts the result
            in register dst.
         */
            the ECMAScript rules is "undefined", and puts the result
            in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
         JSValue v = callFrame->r(src).jsValue();
         callFrame->r(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
 
         JSValue v = callFrame->r(src).jsValue();
         callFrame->r(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_is_undefined);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_boolean) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_boolean) {
@@ -1875,11 +1826,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            the ECMAScript rules is "boolean", and puts the result
            in register dst.
         */
            the ECMAScript rules is "boolean", and puts the result
            in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean());
 
         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean());
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_is_boolean);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_number) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_number) {
@@ -1889,11 +1840,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            the ECMAScript rules is "number", and puts the result
            in register dst.
         */
            the ECMAScript rules is "number", and puts the result
            in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber());
 
         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber());
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_is_number);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_string) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_string) {
@@ -1903,11 +1854,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            the ECMAScript rules is "string", and puts the result
            in register dst.
         */
            the ECMAScript rules is "string", and puts the result
            in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isString());
 
         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isString());
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_is_string);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_object) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_object) {
@@ -1917,11 +1868,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            the ECMAScript rules is "object", and puts the result
            in register dst.
         */
            the ECMAScript rules is "object", and puts the result
            in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
         callFrame->r(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue()));
 
         callFrame->r(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue()));
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_is_object);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_function) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_is_function) {
@@ -1931,11 +1882,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            the ECMAScript rules is "function", and puts the result
            in register dst.
         */
            the ECMAScript rules is "function", and puts the result
            in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
         callFrame->r(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue()));
 
         callFrame->r(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue()));
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_is_function);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_in) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_in) {
@@ -1947,9 +1898,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Raises an exception if register constructor is not an
            object.
         */
            Raises an exception if register constructor is not an
            object.
         */
-        int dst = (++vPC)->u.operand;
-        int property = (++vPC)->u.operand;
-        int base = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int property = vPC[2].u.operand;
+        int base = vPC[3].u.operand;
 
         JSValue baseVal = callFrame->r(base).jsValue();
         if (isInvalidParamForIn(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
 
         JSValue baseVal = callFrame->r(base).jsValue();
         if (isInvalidParamForIn(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
@@ -1968,7 +1919,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
         }
 
             callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_in);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_resolve) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_resolve) {
@@ -1981,7 +1932,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         if (UNLIKELY(!resolve(callFrame, vPC, exceptionValue)))
             goto vm_throw;
 
         if (UNLIKELY(!resolve(callFrame, vPC, exceptionValue)))
             goto vm_throw;
 
-        vPC += 3;
+        vPC += OPCODE_LENGTH(op_resolve);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_resolve_skip) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_resolve_skip) {
@@ -1994,7 +1945,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         if (UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue)))
             goto vm_throw;
 
         if (UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue)))
             goto vm_throw;
 
-        vPC += 4;
+        vPC += OPCODE_LENGTH(op_resolve_skip);
 
         NEXT_INSTRUCTION();
     }
 
         NEXT_INSTRUCTION();
     }
@@ -2009,7 +1960,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue)))
             goto vm_throw;
         
         if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue)))
             goto vm_throw;
         
-        vPC += 6;
+        vPC += OPCODE_LENGTH(op_resolve_global);
         
         NEXT_INSTRUCTION();
     }
         
         NEXT_INSTRUCTION();
     }
@@ -2018,13 +1969,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
            Gets the global var at global slot index and places it in register dst.
          */
 
            Gets the global var at global slot index and places it in register dst.
          */
-        int dst = (++vPC)->u.operand;
-        JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
+        int dst = vPC[1].u.operand;
+        JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[2].u.jsCell);
         ASSERT(scope->isGlobalObject());
         ASSERT(scope->isGlobalObject());
-        int index = (++vPC)->u.operand;
+        int index = vPC[3].u.operand;
 
         callFrame->r(dst) = scope->registerAt(index);
 
         callFrame->r(dst) = scope->registerAt(index);
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_get_global_var);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_global_var) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_global_var) {
@@ -2032,13 +1983,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
          
            Puts value into global slot index.
          */
          
            Puts value into global slot index.
          */
-        JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
+        JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[1].u.jsCell);
         ASSERT(scope->isGlobalObject());
         ASSERT(scope->isGlobalObject());
-        int index = (++vPC)->u.operand;
-        int value = (++vPC)->u.operand;
+        int index = vPC[2].u.operand;
+        int value = vPC[3].u.operand;
         
         scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
         
         scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_put_global_var);
         NEXT_INSTRUCTION();
     }            
     DEFINE_OPCODE(op_get_scoped_var) {
         NEXT_INSTRUCTION();
     }            
     DEFINE_OPCODE(op_get_scoped_var) {
@@ -2047,9 +1998,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
          Loads the contents of the index-th local from the scope skip nodes from
          the top of the scope chain, and places it in register dst
          */
          Loads the contents of the index-th local from the scope skip nodes from
          the top of the scope chain, and places it in register dst
          */
-        int dst = (++vPC)->u.operand;
-        int index = (++vPC)->u.operand;
-        int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain();
+        int dst = vPC[1].u.operand;
+        int index = vPC[2].u.operand;
+        int skip = vPC[3].u.operand + callFrame->codeBlock()->needsFullScopeChain();
 
         ScopeChainNode* scopeChain = callFrame->scopeChain();
         ScopeChainIterator iter = scopeChain->begin();
 
         ScopeChainNode* scopeChain = callFrame->scopeChain();
         ScopeChainIterator iter = scopeChain->begin();
@@ -2063,16 +2014,16 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         ASSERT((*iter)->isVariableObject());
         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
         callFrame->r(dst) = scope->registerAt(index);
         ASSERT((*iter)->isVariableObject());
         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
         callFrame->r(dst) = scope->registerAt(index);
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_get_scoped_var);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_scoped_var) {
         /* put_scoped_var index(n) skip(n) value(r)
 
          */
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_scoped_var) {
         /* put_scoped_var index(n) skip(n) value(r)
 
          */
-        int index = (++vPC)->u.operand;
-        int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain();
-        int value = (++vPC)->u.operand;
+        int index = vPC[1].u.operand;
+        int skip = vPC[2].u.operand + callFrame->codeBlock()->needsFullScopeChain();
+        int value = vPC[3].u.operand;
 
         ScopeChainNode* scopeChain = callFrame->scopeChain();
         ScopeChainIterator iter = scopeChain->begin();
 
         ScopeChainNode* scopeChain = callFrame->scopeChain();
         ScopeChainIterator iter = scopeChain->begin();
@@ -2086,7 +2037,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         ASSERT((*iter)->isVariableObject());
         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
         scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
         ASSERT((*iter)->isVariableObject());
         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
         scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_put_scoped_var);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_resolve_base) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_resolve_base) {
@@ -2099,7 +2050,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         resolveBase(callFrame, vPC);
 
         */
         resolveBase(callFrame, vPC);
 
-        vPC += 3;
+        vPC += OPCODE_LENGTH(op_resolve_base);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_resolve_with_base) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_resolve_with_base) {
@@ -2117,7 +2068,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         if (UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue)))
             goto vm_throw;
 
         if (UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue)))
             goto vm_throw;
 
-        vPC += 4;
+        vPC += OPCODE_LENGTH(op_resolve_with_base);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_id) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_id) {
@@ -2140,7 +2091,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
 
         callFrame->r(dst) = result;
         tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
 
         callFrame->r(dst) = result;
-        vPC += 8;
+        vPC += OPCODE_LENGTH(op_get_by_id);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_id_self) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_id_self) {
@@ -2166,7 +2117,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                 ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
                 callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
 
                 ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
                 callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
 
-                vPC += 8;
+                vPC += OPCODE_LENGTH(op_get_by_id_self);
                 NEXT_INSTRUCTION();
             }
         }
                 NEXT_INSTRUCTION();
             }
         }
@@ -2201,7 +2152,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                     ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
                     callFrame->r(dst) = JSValue(protoObject->getDirectOffset(offset));
 
                     ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
                     callFrame->r(dst) = JSValue(protoObject->getDirectOffset(offset));
 
-                    vPC += 8;
+                    vPC += OPCODE_LENGTH(op_get_by_id_proto);
                     NEXT_INSTRUCTION();
                 }
             }
                     NEXT_INSTRUCTION();
                 }
             }
@@ -2214,14 +2165,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         // Polymorphic self access caching currently only supported when JITting.
         ASSERT_NOT_REACHED();
         // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
         // Polymorphic self access caching currently only supported when JITting.
         ASSERT_NOT_REACHED();
         // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
-        vPC += 8;
+        vPC += OPCODE_LENGTH(op_get_by_id_self_list);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_id_proto_list) {
         // Polymorphic prototype access caching currently only supported when JITting.
         ASSERT_NOT_REACHED();
         // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_id_proto_list) {
         // Polymorphic prototype access caching currently only supported when JITting.
         ASSERT_NOT_REACHED();
         // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
-        vPC += 8;
+        vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_id_chain) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_id_chain) {
@@ -2257,7 +2208,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                         ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
                         callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
 
                         ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
                         callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
 
-                        vPC += 8;
+                        vPC += OPCODE_LENGTH(op_get_by_id_chain);
                         NEXT_INSTRUCTION();
                     }
 
                         NEXT_INSTRUCTION();
                     }
 
@@ -2287,7 +2238,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         CHECK_FOR_EXCEPTION();
 
         callFrame->r(dst) = result;
         CHECK_FOR_EXCEPTION();
 
         callFrame->r(dst) = result;
-        vPC += 8;
+        vPC += OPCODE_LENGTH(op_get_by_id_generic);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_array_length) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_array_length) {
@@ -2303,7 +2254,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         if (LIKELY(isJSArray(globalData, baseValue))) {
             int dst = vPC[1].u.operand;
             callFrame->r(dst) = jsNumber(callFrame, asArray(baseValue)->length());
         if (LIKELY(isJSArray(globalData, baseValue))) {
             int dst = vPC[1].u.operand;
             callFrame->r(dst) = jsNumber(callFrame, asArray(baseValue)->length());
-            vPC += 8;
+            vPC += OPCODE_LENGTH(op_get_array_length);
             NEXT_INSTRUCTION();
         }
 
             NEXT_INSTRUCTION();
         }
 
@@ -2322,8 +2273,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue baseValue = callFrame->r(base).jsValue();
         if (LIKELY(isJSString(globalData, baseValue))) {
             int dst = vPC[1].u.operand;
         JSValue baseValue = callFrame->r(base).jsValue();
         if (LIKELY(isJSString(globalData, baseValue))) {
             int dst = vPC[1].u.operand;
-            callFrame->r(dst) = jsNumber(callFrame, asString(baseValue)->value().size());
-            vPC += 8;
+            callFrame->r(dst) = jsNumber(callFrame, asString(baseValue)->length());
+            vPC += OPCODE_LENGTH(op_get_string_length);
             NEXT_INSTRUCTION();
         }
 
             NEXT_INSTRUCTION();
         }
 
@@ -2353,7 +2304,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
 
 
         tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
 
-        vPC += 8;
+        vPC += OPCODE_LENGTH(op_put_by_id);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_by_id_transition) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_by_id_transition) {
@@ -2398,7 +2349,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
                 baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
 
                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
                 baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
 
-                vPC += 8;
+                vPC += OPCODE_LENGTH(op_put_by_id_transition);
                 NEXT_INSTRUCTION();
             }
         }
                 NEXT_INSTRUCTION();
             }
         }
@@ -2433,7 +2384,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
                 baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
 
                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
                 baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
 
-                vPC += 8;
+                vPC += OPCODE_LENGTH(op_put_by_id_replace);
                 NEXT_INSTRUCTION();
             }
         }
                 NEXT_INSTRUCTION();
             }
         }
@@ -2460,7 +2411,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
         CHECK_FOR_EXCEPTION();
 
         baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
         CHECK_FOR_EXCEPTION();
 
-        vPC += 8;
+        vPC += OPCODE_LENGTH(op_put_by_id_generic);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_del_by_id) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_del_by_id) {
@@ -2471,16 +2422,43 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            boolean indicating success (if true) or failure (if false)
            to register dst.
         */
            boolean indicating success (if true) or failure (if false)
            to register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int base = (++vPC)->u.operand;
-        int property = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int base = vPC[2].u.operand;
+        int property = vPC[3].u.operand;
 
         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
         Identifier& ident = callFrame->codeBlock()->identifier(property);
         JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
         Identifier& ident = callFrame->codeBlock()->identifier(property);
         JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_del_by_id);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_get_by_pname) {
+        int dst = vPC[1].u.operand;
+        int base = vPC[2].u.operand;
+        int property = vPC[3].u.operand;
+        int expected = vPC[4].u.operand;
+        int iter = vPC[5].u.operand;
+        int i = vPC[6].u.operand;
+
+        JSValue baseValue = callFrame->r(base).jsValue();
+        JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
+        JSValue subscript = callFrame->r(property).jsValue();
+        JSValue expectedSubscript = callFrame->r(expected).jsValue();
+        int index = callFrame->r(i).i() - 1;
+        JSValue result;
+        int offset = 0;
+        if (subscript == expectedSubscript && baseValue.isCell() && (baseValue.asCell()->structure() == it->cachedStructure()) && it->getOffset(index, offset)) {
+            callFrame->r(dst) = asObject(baseValue)->getDirectOffset(offset);
+            vPC += OPCODE_LENGTH(op_get_by_pname);
+            NEXT_INSTRUCTION();
+        }
+        Identifier propertyName(callFrame, subscript.toString(callFrame));
+        result = baseValue.get(callFrame, propertyName);
+        CHECK_FOR_EXCEPTION();
+        callFrame->r(dst) = result;
+        vPC += OPCODE_LENGTH(op_get_by_pname);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_val) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_val) {
@@ -2491,9 +2469,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            in register dst. property is nominally converted to string
            but numbers are treated more efficiently.
         */
            in register dst. property is nominally converted to string
            but numbers are treated more efficiently.
         */
-        int dst = (++vPC)->u.operand;
-        int base = (++vPC)->u.operand;
-        int property = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int base = vPC[2].u.operand;
+        int property = vPC[3].u.operand;
         
         JSValue baseValue = callFrame->r(base).jsValue();
         JSValue subscript = callFrame->r(property).jsValue();
         
         JSValue baseValue = callFrame->r(base).jsValue();
         JSValue subscript = callFrame->r(property).jsValue();
@@ -2509,7 +2487,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                 else
                     result = jsArray->JSArray::get(callFrame, i);
             } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
                 else
                     result = jsArray->JSArray::get(callFrame, i);
             } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
-                result = asString(baseValue)->getIndex(&callFrame->globalData(), i);
+                result = asString(baseValue)->getIndex(callFrame, i);
             else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i))
                 result = asByteArray(baseValue)->getIndex(callFrame, i);
             else
             else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i))
                 result = asByteArray(baseValue)->getIndex(callFrame, i);
             else
@@ -2521,7 +2499,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_get_by_val);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_by_val) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_by_val) {
@@ -2535,9 +2513,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Unlike many opcodes, this one does not write any output to
            the register file.
         */
            Unlike many opcodes, this one does not write any output to
            the register file.
         */
-        int base = (++vPC)->u.operand;
-        int property = (++vPC)->u.operand;
-        int value = (++vPC)->u.operand;
+        int base = vPC[1].u.operand;
+        int property = vPC[2].u.operand;
+        int value = vPC[3].u.operand;
 
         JSValue baseValue = callFrame->r(base).jsValue();
         JSValue subscript = callFrame->r(property).jsValue();
 
         JSValue baseValue = callFrame->r(base).jsValue();
         JSValue subscript = callFrame->r(property).jsValue();
@@ -2571,7 +2549,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         }
 
         CHECK_FOR_EXCEPTION();
         }
 
         CHECK_FOR_EXCEPTION();
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_put_by_val);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_del_by_val) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_del_by_val) {
@@ -2582,9 +2560,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            boolean indicating success (if true) or failure (if false)
            to register dst.
         */
            boolean indicating success (if true) or failure (if false)
            to register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int base = (++vPC)->u.operand;
-        int property = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int base = vPC[2].u.operand;
+        int property = vPC[3].u.operand;
 
         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw
 
 
         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw
 
@@ -2602,7 +2580,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
 
         CHECK_FOR_EXCEPTION();
         callFrame->r(dst) = result;
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_del_by_val);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_by_index) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_by_index) {
@@ -2617,13 +2595,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
            This opcode is mainly used to initialize array literals.
         */
 
            This opcode is mainly used to initialize array literals.
         */
-        int base = (++vPC)->u.operand;
-        unsigned property = (++vPC)->u.operand;
-        int value = (++vPC)->u.operand;
+        int base = vPC[1].u.operand;
+        unsigned property = vPC[2].u.operand;
+        int value = vPC[3].u.operand;
 
         callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue());
 
 
         callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue());
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_put_by_index);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_loop) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_loop) {
@@ -2638,7 +2616,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 #if ENABLE(OPCODE_STATS)
         OpcodeStats::resetLastInstruction();
 #endif
 #if ENABLE(OPCODE_STATS)
         OpcodeStats::resetLastInstruction();
 #endif
-        int target = (++vPC)->u.operand;
+        int target = vPC[1].u.operand;
         CHECK_FOR_TIMEOUT();
         vPC += target;
         NEXT_INSTRUCTION();
         CHECK_FOR_TIMEOUT();
         vPC += target;
         NEXT_INSTRUCTION();
@@ -2652,7 +2630,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 #if ENABLE(OPCODE_STATS)
         OpcodeStats::resetLastInstruction();
 #endif
 #if ENABLE(OPCODE_STATS)
         OpcodeStats::resetLastInstruction();
 #endif
-        int target = (++vPC)->u.operand;
+        int target = vPC[1].u.operand;
 
         vPC += target;
         NEXT_INSTRUCTION();
 
         vPC += target;
         NEXT_INSTRUCTION();
@@ -2666,15 +2644,35 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Additionally this loop instruction may terminate JS execution is
            the JS timeout is reached.
          */
            Additionally this loop instruction may terminate JS execution is
            the JS timeout is reached.
          */
-        int cond = (++vPC)->u.operand;
-        int target = (++vPC)->u.operand;
+        int cond = vPC[1].u.operand;
+        int target = vPC[2].u.operand;
         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
             vPC += target;
             CHECK_FOR_TIMEOUT();
             NEXT_INSTRUCTION();
         }
         
         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
             vPC += target;
             CHECK_FOR_TIMEOUT();
             NEXT_INSTRUCTION();
         }
         
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_loop_if_true);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_loop_if_false) {
+        /* loop_if_true cond(r) target(offset)
+         
+           Jumps to offset target from the current instruction, if and
+           only if register cond converts to boolean as false.
+
+           Additionally this loop instruction may terminate JS execution is
+           the JS timeout is reached.
+         */
+        int cond = vPC[1].u.operand;
+        int target = vPC[2].u.operand;
+        if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
+            vPC += target;
+            CHECK_FOR_TIMEOUT();
+            NEXT_INSTRUCTION();
+        }
+        
+        vPC += OPCODE_LENGTH(op_loop_if_true);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jtrue) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jtrue) {
@@ -2683,14 +2681,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Jumps to offset target from the current instruction, if and
            only if register cond converts to boolean as true.
         */
            Jumps to offset target from the current instruction, if and
            only if register cond converts to boolean as true.
         */
-        int cond = (++vPC)->u.operand;
-        int target = (++vPC)->u.operand;
+        int cond = vPC[1].u.operand;
+        int target = vPC[2].u.operand;
         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
             vPC += target;
             NEXT_INSTRUCTION();
         }
 
         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
             vPC += target;
             NEXT_INSTRUCTION();
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_jtrue);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jfalse) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jfalse) {
@@ -2699,14 +2697,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Jumps to offset target from the current instruction, if and
            only if register cond converts to boolean as false.
         */
            Jumps to offset target from the current instruction, if and
            only if register cond converts to boolean as false.
         */
-        int cond = (++vPC)->u.operand;
-        int target = (++vPC)->u.operand;
+        int cond = vPC[1].u.operand;
+        int target = vPC[2].u.operand;
         if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
             vPC += target;
             NEXT_INSTRUCTION();
         }
 
         if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
             vPC += target;
             NEXT_INSTRUCTION();
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_jfalse);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jeq_null) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jeq_null) {
@@ -2715,8 +2713,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Jumps to offset target from the current instruction, if and
            only if register src is null.
         */
            Jumps to offset target from the current instruction, if and
            only if register src is null.
         */
-        int src = (++vPC)->u.operand;
-        int target = (++vPC)->u.operand;
+        int src = vPC[1].u.operand;
+        int target = vPC[2].u.operand;
         JSValue srcValue = callFrame->r(src).jsValue();
 
         if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
         JSValue srcValue = callFrame->r(src).jsValue();
 
         if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
@@ -2724,7 +2722,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             NEXT_INSTRUCTION();
         }
 
             NEXT_INSTRUCTION();
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_jeq_null);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jneq_null) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jneq_null) {
@@ -2733,16 +2731,16 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Jumps to offset target from the current instruction, if and
            only if register src is not null.
         */
            Jumps to offset target from the current instruction, if and
            only if register src is not null.
         */
-        int src = (++vPC)->u.operand;
-        int target = (++vPC)->u.operand;
+        int src = vPC[1].u.operand;
+        int target = vPC[2].u.operand;
         JSValue srcValue = callFrame->r(src).jsValue();
 
         JSValue srcValue = callFrame->r(src).jsValue();
 
-        if (!srcValue.isUndefinedOrNull() || (srcValue.isCell() && !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
+        if (!srcValue.isUndefinedOrNull() && (!srcValue.isCell() || !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
             vPC += target;
             NEXT_INSTRUCTION();
         }
 
             vPC += target;
             NEXT_INSTRUCTION();
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_jneq_null);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jneq_ptr) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jneq_ptr) {
@@ -2751,16 +2749,16 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Jumps to offset target from the current instruction, if the value r is equal
            to ptr, using pointer equality.
          */
            Jumps to offset target from the current instruction, if the value r is equal
            to ptr, using pointer equality.
          */
-        int src = (++vPC)->u.operand;
-        JSValue ptr = JSValue((++vPC)->u.jsCell);
-        int target = (++vPC)->u.operand;
+        int src = vPC[1].u.operand;
+        JSValue ptr = JSValue(vPC[2].u.jsCell);
+        int target = vPC[3].u.operand;
         JSValue srcValue = callFrame->r(src).jsValue();
         if (srcValue != ptr) {
             vPC += target;
             NEXT_INSTRUCTION();
         }
 
         JSValue srcValue = callFrame->r(src).jsValue();
         if (srcValue != ptr) {
             vPC += target;
             NEXT_INSTRUCTION();
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_jneq_ptr);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_loop_if_less) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_loop_if_less) {
@@ -2774,9 +2772,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Additionally this loop instruction may terminate JS execution is
            the JS timeout is reached.
          */
            Additionally this loop instruction may terminate JS execution is
            the JS timeout is reached.
          */
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
-        int target = (++vPC)->u.operand;
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
         
         bool result = jsLess(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
         
         bool result = jsLess(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
@@ -2787,7 +2785,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             NEXT_INSTRUCTION();
         }
         
             NEXT_INSTRUCTION();
         }
         
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_loop_if_less);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_loop_if_lesseq) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_loop_if_lesseq) {
@@ -2801,9 +2799,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Additionally this loop instruction may terminate JS execution is
            the JS timeout is reached.
         */
            Additionally this loop instruction may terminate JS execution is
            the JS timeout is reached.
         */
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
-        int target = (++vPC)->u.operand;
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
         
         bool result = jsLessEq(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
         
         bool result = jsLessEq(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
@@ -2814,7 +2812,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             NEXT_INSTRUCTION();
         }
         
             NEXT_INSTRUCTION();
         }
         
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_loop_if_lesseq);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jnless) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jnless) {
@@ -2825,9 +2823,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            target from the current instruction, if and only if the 
            result of the comparison is false.
         */
            target from the current instruction, if and only if the 
            result of the comparison is false.
         */
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
-        int target = (++vPC)->u.operand;
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
 
         bool result = jsLess(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
 
         bool result = jsLess(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
@@ -2837,7 +2835,30 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             NEXT_INSTRUCTION();
         }
 
             NEXT_INSTRUCTION();
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_jnless);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_jless) {
+        /* jless src1(r) src2(r) target(offset)
+
+           Checks whether register src1 is less than register src2, as
+           with the ECMAScript '<' operator, and then jumps to offset
+           target from the current instruction, if and only if the 
+           result of the comparison is true.
+        */
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
+
+        bool result = jsLess(callFrame, src1, src2);
+        CHECK_FOR_EXCEPTION();
+        
+        if (result) {
+            vPC += target;
+            NEXT_INSTRUCTION();
+        }
+
+        vPC += OPCODE_LENGTH(op_jless);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jnlesseq) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jnlesseq) {
@@ -2848,9 +2869,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            and then jumps to offset target from the current instruction,
            if and only if theresult of the comparison is false.
         */
            and then jumps to offset target from the current instruction,
            if and only if theresult of the comparison is false.
         */
-        JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue();
-        JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue();
-        int target = (++vPC)->u.operand;
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
 
         bool result = jsLessEq(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
 
         bool result = jsLessEq(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
@@ -2860,7 +2881,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             NEXT_INSTRUCTION();
         }
 
             NEXT_INSTRUCTION();
         }
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_jnlesseq);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_switch_imm) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_switch_imm) {
@@ -2872,9 +2893,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            table, and the value at jumpTable[scrutinee value] is non-zero, then
            that value is used as the jump offset, otherwise defaultOffset is used.
          */
            table, and the value at jumpTable[scrutinee value] is non-zero, then
            that value is used as the jump offset, otherwise defaultOffset is used.
          */
-        int tableIndex = (++vPC)->u.operand;
-        int defaultOffset = (++vPC)->u.operand;
-        JSValue scrutinee = callFrame->r((++vPC)->u.operand).jsValue();
+        int tableIndex = vPC[1].u.operand;
+        int defaultOffset = vPC[2].u.operand;
+        JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
         if (scrutinee.isInt32())
             vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
         else {
         if (scrutinee.isInt32())
             vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
         else {
@@ -2896,13 +2917,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            table, and the value at jumpTable[scrutinee value] is non-zero, then
            that value is used as the jump offset, otherwise defaultOffset is used.
          */
            table, and the value at jumpTable[scrutinee value] is non-zero, then
            that value is used as the jump offset, otherwise defaultOffset is used.
          */
-        int tableIndex = (++vPC)->u.operand;
-        int defaultOffset = (++vPC)->u.operand;
-        JSValue scrutinee = callFrame->r((++vPC)->u.operand).jsValue();
+        int tableIndex = vPC[1].u.operand;
+        int defaultOffset = vPC[2].u.operand;
+        JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
         if (!scrutinee.isString())
             vPC += defaultOffset;
         else {
         if (!scrutinee.isString())
             vPC += defaultOffset;
         else {
-            UString::Rep* value = asString(scrutinee)->value().rep();
+            UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
             if (value->size() != 1)
                 vPC += defaultOffset;
             else
             if (value->size() != 1)
                 vPC += defaultOffset;
             else
@@ -2919,13 +2940,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            jump table, then the value associated with the string is used as the 
            jump offset, otherwise defaultOffset is used.
          */
            jump table, then the value associated with the string is used as the 
            jump offset, otherwise defaultOffset is used.
          */
-        int tableIndex = (++vPC)->u.operand;
-        int defaultOffset = (++vPC)->u.operand;
-        JSValue scrutinee = callFrame->r((++vPC)->u.operand).jsValue();
+        int tableIndex = vPC[1].u.operand;
+        int defaultOffset = vPC[2].u.operand;
+        JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
         if (!scrutinee.isString())
             vPC += defaultOffset;
         else 
         if (!scrutinee.isString())
             vPC += defaultOffset;
         else 
-            vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value().rep(), defaultOffset);
+            vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value(callFrame).rep(), defaultOffset);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_new_func) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_new_func) {
@@ -2936,12 +2957,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            constructor, using the rules for function declarations, and
            puts the result in register dst.
         */
            constructor, using the rules for function declarations, and
            puts the result in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int func = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int func = vPC[2].u.operand;
 
 
-        callFrame->r(dst) = JSValue(callFrame->codeBlock()->function(func)->makeFunction(callFrame, callFrame->scopeChain()));
+        callFrame->r(dst) = JSValue(callFrame->codeBlock()->functionDecl(func)->make(callFrame, callFrame->scopeChain()));
 
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_new_func);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_new_func_exp) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_new_func_exp) {
@@ -2952,12 +2973,27 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            constructor, using the rules for function expressions, and
            puts the result in register dst.
         */
            constructor, using the rules for function expressions, and
            puts the result in register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int func = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int funcIndex = vPC[2].u.operand;
 
 
-        callFrame->r(dst) = JSValue(callFrame->codeBlock()->functionExpression(func)->makeFunction(callFrame, callFrame->scopeChain()));
+        FunctionExecutable* function = callFrame->codeBlock()->functionExpr(funcIndex);
+        JSFunction* func = function->make(callFrame, callFrame->scopeChain());
+
+        /* 
+            The Identifier in a FunctionExpression can be referenced from inside
+            the FunctionExpression's FunctionBody to allow the function to call
+            itself recursively. However, unlike in a FunctionDeclaration, the
+            Identifier in a FunctionExpression cannot be referenced from and
+            does not affect the scope enclosing the FunctionExpression.
+         */
+        if (!function->name().isNull()) {
+            JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
+            func->scope().push(functionScopeObject);
+        }
 
 
-        ++vPC;
+        callFrame->r(dst) = JSValue(func);
+
+        vPC += OPCODE_LENGTH(op_new_func_exp);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_call_eval) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_call_eval) {
@@ -2982,7 +3018,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         Register* newCallFrame = callFrame->registers() + registerOffset;
         Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
         JSValue thisValue = argv[0].jsValue();
         Register* newCallFrame = callFrame->registers() + registerOffset;
         Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
         JSValue thisValue = argv[0].jsValue();
-        JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
+        JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
 
         if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
             JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
 
         if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
             JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
@@ -2990,7 +3026,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                 goto vm_throw;
             callFrame->r(dst) = result;
 
                 goto vm_throw;
             callFrame->r(dst) = result;
 
-            vPC += 5;
+            vPC += OPCODE_LENGTH(op_call_eval);
             NEXT_INSTRUCTION();
         }
 
             NEXT_INSTRUCTION();
         }
 
@@ -3021,8 +3057,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         if (callType == CallTypeJS) {
             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
 
         if (callType == CallTypeJS) {
             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
-            FunctionBodyNode* functionBodyNode = callData.js.functionBody;
-            CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
+            CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
 
             CallFrame* previousCallFrame = callFrame;
 
 
             CallFrame* previousCallFrame = callFrame;
 
@@ -3058,14 +3093,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
             JSValue returnValue;
             {
 
             JSValue returnValue;
             {
-                SamplingTool::HostCallRecord callRecord(m_sampler);
+                SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
             }
             CHECK_FOR_EXCEPTION();
 
             callFrame->r(dst) = returnValue;
 
                 returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
             }
             CHECK_FOR_EXCEPTION();
 
             callFrame->r(dst) = returnValue;
 
-            vPC += 5;
+            vPC += OPCODE_LENGTH(op_call);
             NEXT_INSTRUCTION();
         }
 
             NEXT_INSTRUCTION();
         }
 
@@ -3075,8 +3110,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         goto vm_throw;
     }
     DEFINE_OPCODE(op_load_varargs) {
         goto vm_throw;
     }
     DEFINE_OPCODE(op_load_varargs) {
-        int argCountDst = (++vPC)->u.operand;
-        int argsOffset = (++vPC)->u.operand;
+        int argCountDst = vPC[1].u.operand;
+        int argsOffset = vPC[2].u.operand;
         
         JSValue arguments = callFrame->r(argsOffset).jsValue();
         int32_t argCount = 0;
         
         JSValue arguments = callFrame->r(argsOffset).jsValue();
         int32_t argCount = 0;
@@ -3088,7 +3123,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                 exceptionValue = createStackOverflowError(callFrame);
                 goto vm_throw;
             }
                 exceptionValue = createStackOverflowError(callFrame);
                 goto vm_throw;
             }
-            int32_t expectedParams = callFrame->callee()->body()->parameterCount();
+            ASSERT(!callFrame->callee()->isHostFunction());
+            int32_t expectedParams = callFrame->callee()->jsExecutable()->parameterCount();
             int32_t inplaceArgs = min(argCount, expectedParams);
             int32_t i = 0;
             Register* argStore = callFrame->registers() + argsOffset;
             int32_t inplaceArgs = min(argCount, expectedParams);
             int32_t i = 0;
             Register* argStore = callFrame->registers() + argsOffset;
@@ -3147,7 +3183,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         }
         CHECK_FOR_EXCEPTION();
         callFrame->r(argCountDst) = Register::withInt(argCount + 1);
         }
         CHECK_FOR_EXCEPTION();
         callFrame->r(argCountDst) = Register::withInt(argCount + 1);
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_load_varargs);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_call_varargs) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_call_varargs) {
@@ -3175,8 +3211,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         
         if (callType == CallTypeJS) {
             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
         
         if (callType == CallTypeJS) {
             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
-            FunctionBodyNode* functionBodyNode = callData.js.functionBody;
-            CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
+            CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
             
             CallFrame* previousCallFrame = callFrame;
             
             
             CallFrame* previousCallFrame = callFrame;
             
@@ -3212,14 +3247,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             
             JSValue returnValue;
             {
             
             JSValue returnValue;
             {
-                SamplingTool::HostCallRecord callRecord(m_sampler);
+                SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
             }
             CHECK_FOR_EXCEPTION();
             
             callFrame->r(dst) = returnValue;
             
                 returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
             }
             CHECK_FOR_EXCEPTION();
             
             callFrame->r(dst) = returnValue;
             
-            vPC += 5;
+            vPC += OPCODE_LENGTH(op_call_varargs);
             NEXT_INSTRUCTION();
         }
         
             NEXT_INSTRUCTION();
         }
         
@@ -3241,12 +3276,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            This opcode should only be used immediately before op_ret.
         */
 
            This opcode should only be used immediately before op_ret.
         */
 
-        int src = (++vPC)->u.operand;
+        int src = vPC[1].u.operand;
         ASSERT(callFrame->codeBlock()->needsFullScopeChain());
 
         asActivation(callFrame->r(src).jsValue())->copyRegisters(callFrame->optionalCalleeArguments());
 
         ASSERT(callFrame->codeBlock()->needsFullScopeChain());
 
         asActivation(callFrame->r(src).jsValue())->copyRegisters(callFrame->optionalCalleeArguments());
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_tear_off_activation);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_tear_off_arguments) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_tear_off_arguments) {
@@ -3267,7 +3302,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         if (callFrame->optionalCalleeArguments())
             callFrame->optionalCalleeArguments()->copyRegisters();
 
         if (callFrame->optionalCalleeArguments())
             callFrame->optionalCalleeArguments()->copyRegisters();
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_tear_off_arguments);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_ret) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_ret) {
@@ -3280,7 +3315,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            register base to those of the calling function.
         */
 
            register base to those of the calling function.
         */
 
-        int result = (++vPC)->u.operand;
+        int result = vPC[1].u.operand;
 
         if (callFrame->codeBlock()->needsFullScopeChain())
             callFrame->scopeChain()->deref();
 
         if (callFrame->codeBlock()->needsFullScopeChain())
             callFrame->scopeChain()->deref();
@@ -3315,7 +3350,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         for (size_t count = codeBlock->m_numVars; i < count; ++i)
             callFrame->r(i) = jsUndefined();
 
         for (size_t count = codeBlock->m_numVars; i < count; ++i)
             callFrame->r(i) = jsUndefined();
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_enter);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_enter_with_activation) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_enter_with_activation) {
@@ -3337,12 +3372,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         for (size_t count = codeBlock->m_numVars; i < count; ++i)
             callFrame->r(i) = jsUndefined();
 
         for (size_t count = codeBlock->m_numVars; i < count; ++i)
             callFrame->r(i) = jsUndefined();
 
-        int dst = (++vPC)->u.operand;
-        JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionBodyNode*>(codeBlock->ownerNode()));
+        int dst = vPC[1].u.operand;
+        JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
         callFrame->r(dst) = JSValue(activation);
         callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
 
         callFrame->r(dst) = JSValue(activation);
         callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_enter_with_activation);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_convert_this) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_convert_this) {
@@ -3357,12 +3392,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            block.
         */
 
            block.
         */
 
-        int thisRegister = (++vPC)->u.operand;
+        int thisRegister = vPC[1].u.operand;
         JSValue thisVal = callFrame->r(thisRegister).jsValue();
         if (thisVal.needsThisConversion())
             callFrame->r(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
 
         JSValue thisVal = callFrame->r(thisRegister).jsValue();
         if (thisVal.needsThisConversion())
             callFrame->r(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_convert_this);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_init_arguments) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_init_arguments) {
@@ -3376,7 +3411,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            block.
          */
         callFrame->r(RegisterFile::ArgumentsRegister) = JSValue();
            block.
          */
         callFrame->r(RegisterFile::ArgumentsRegister) = JSValue();
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_init_arguments);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_create_arguments) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_create_arguments) {
@@ -3392,7 +3427,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
              callFrame->setCalleeArguments(arguments);
              callFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments);
          }
              callFrame->setCalleeArguments(arguments);
              callFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments);
          }
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_create_arguments);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_construct) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_construct) {
@@ -3424,15 +3459,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         if (constructType == ConstructTypeJS) {
             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
 
         if (constructType == ConstructTypeJS) {
             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
-            FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
-            CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
+            CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
 
             Structure* structure;
             JSValue prototype = callFrame->r(proto).jsValue();
             if (prototype.isObject())
                 structure = asObject(prototype)->inheritorID();
             else
 
             Structure* structure;
             JSValue prototype = callFrame->r(proto).jsValue();
             if (prototype.isObject())
                 structure = asObject(prototype)->inheritorID();
             else
-                structure = callDataScopeChain->globalObject()->emptyObjectStructure();
+                structure = callDataScopeChain->globalObject->emptyObjectStructure();
             JSObject* newObject = new (globalData) JSObject(structure);
 
             callFrame->r(thisRegister) = JSValue(newObject); // "this" value
             JSObject* newObject = new (globalData) JSObject(structure);
 
             callFrame->r(thisRegister) = JSValue(newObject); // "this" value
@@ -3465,13 +3499,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
             JSValue returnValue;
             {
 
             JSValue returnValue;
             {
-                SamplingTool::HostCallRecord callRecord(m_sampler);
+                SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = constructData.native.function(newCallFrame, asObject(v), args);
             }
             CHECK_FOR_EXCEPTION();
             callFrame->r(dst) = JSValue(returnValue);
 
                 returnValue = constructData.native.function(newCallFrame, asObject(v), args);
             }
             CHECK_FOR_EXCEPTION();
             callFrame->r(dst) = JSValue(returnValue);
 
-            vPC += 7;
+            vPC += OPCODE_LENGTH(op_construct);
             NEXT_INSTRUCTION();
         }
 
             NEXT_INSTRUCTION();
         }
 
@@ -3489,32 +3523,33 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         int dst = vPC[1].u.operand;
         if (LIKELY(callFrame->r(dst).jsValue().isObject())) {
 
         int dst = vPC[1].u.operand;
         if (LIKELY(callFrame->r(dst).jsValue().isObject())) {
-            vPC += 3;
+            vPC += OPCODE_LENGTH(op_construct_verify);
             NEXT_INSTRUCTION();
         }
 
         int override = vPC[2].u.operand;
         callFrame->r(dst) = callFrame->r(override);
 
             NEXT_INSTRUCTION();
         }
 
         int override = vPC[2].u.operand;
         callFrame->r(dst) = callFrame->r(override);
 
-        vPC += 3;
+        vPC += OPCODE_LENGTH(op_construct_verify);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_strcat) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_strcat) {
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
-        int count = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
+        int count = vPC[3].u.operand;
 
 
-        callFrame->r(dst) = concatenateStrings(callFrame, &callFrame->registers()[src], count);
-        ++vPC;
+        callFrame->r(dst) = jsString(callFrame, &callFrame->registers()[src], count);
+        CHECK_FOR_EXCEPTION();
+        vPC += OPCODE_LENGTH(op_strcat);
 
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_to_primitive) {
 
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_to_primitive) {
-        int dst = (++vPC)->u.operand;
-        int src = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int src = vPC[2].u.operand;
 
         callFrame->r(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame);
 
         callFrame->r(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame);
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_to_primitive);
 
         NEXT_INSTRUCTION();
     }
 
         NEXT_INSTRUCTION();
     }
@@ -3525,7 +3560,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            of the current scope chain.  The contents of the register scope
            are replaced by the result of toObject conversion of the scope.
         */
            of the current scope chain.  The contents of the register scope
            are replaced by the result of toObject conversion of the scope.
         */
-        int scope = (++vPC)->u.operand;
+        int scope = vPC[1].u.operand;
         JSValue v = callFrame->r(scope).jsValue();
         JSObject* o = v.toObject(callFrame);
         CHECK_FOR_EXCEPTION();
         JSValue v = callFrame->r(scope).jsValue();
         JSObject* o = v.toObject(callFrame);
         CHECK_FOR_EXCEPTION();
@@ -3533,7 +3568,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         callFrame->r(scope) = JSValue(o);
         callFrame->setScopeChain(callFrame->scopeChain()->push(o));
 
         callFrame->r(scope) = JSValue(o);
         callFrame->setScopeChain(callFrame->scopeChain()->push(o));
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_push_scope);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_pop_scope) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_pop_scope) {
@@ -3543,47 +3578,69 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         callFrame->setScopeChain(callFrame->scopeChain()->pop());
 
         */
         callFrame->setScopeChain(callFrame->scopeChain()->pop());
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_pop_scope);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_pnames) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_pnames) {
-        /* get_pnames dst(r) base(r)
+        /* get_pnames dst(r) base(r) i(n) size(n) breakTarget(offset)
 
            Creates a property name list for register base and puts it
 
            Creates a property name list for register base and puts it
-           in register dst. This is not a true JavaScript value, just
-           a synthetic value used to keep the iteration state in a
-           register.
+           in register dst, initializing i and size for iteration. If
+           base is undefined or null, jumps to breakTarget.
         */
         */
-        int dst = (++vPC)->u.operand;
-        int base = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int base = vPC[2].u.operand;
+        int i = vPC[3].u.operand;
+        int size = vPC[4].u.operand;
+        int breakTarget = vPC[5].u.operand;
+
+        JSValue v = callFrame->r(base).jsValue();
+        if (v.isUndefinedOrNull()) {
+            vPC += breakTarget;
+            NEXT_INSTRUCTION();
+        }
+
+        JSObject* o = v.toObject(callFrame);
+        Structure* structure = o->structure();
+        JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
+        if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
+            jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
 
 
-        callFrame->r(dst) = JSPropertyNameIterator::create(callFrame, callFrame->r(base).jsValue());
-        ++vPC;
+        callFrame->r(dst) = jsPropertyNameIterator;
+        callFrame->r(base) = JSValue(o);
+        callFrame->r(i) = Register::withInt(0);
+        callFrame->r(size) = Register::withInt(jsPropertyNameIterator->size());
+        vPC += OPCODE_LENGTH(op_get_pnames);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_next_pname) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_next_pname) {
-        /* next_pname dst(r) iter(r) target(offset)
+        /* next_pname dst(r) base(r) i(n) size(n) iter(r) target(offset)
 
 
-           Tries to copies the next name from property name list in
-           register iter. If there are names left, then copies one to
-           register dst, and jumps to offset target. If there are none
-           left, invalidates the iterator and continues to the next
+           Copies the next name from the property name list in
+           register iter to dst, then jumps to offset target. If there are no
+           names left, invalidates the iterator and continues to the next
            instruction.
         */
            instruction.
         */
-        int dst = (++vPC)->u.operand;
-        int iter = (++vPC)->u.operand;
-        int target = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int base = vPC[2].u.operand;
+        int i = vPC[3].u.operand;
+        int size = vPC[4].u.operand;
+        int iter = vPC[5].u.operand;
+        int target = vPC[6].u.operand;
 
         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
 
         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
-        if (JSValue temp = it->next(callFrame)) {
-            CHECK_FOR_TIMEOUT();
-            callFrame->r(dst) = JSValue(temp);
-            vPC += target;
-            NEXT_INSTRUCTION();
+        while (callFrame->r(i).i() != callFrame->r(size).i()) {
+            JSValue key = it->get(callFrame, asObject(callFrame->r(base).jsValue()), callFrame->r(i).i());
+            callFrame->r(i) = Register::withInt(callFrame->r(i).i() + 1);
+            if (key) {
+                CHECK_FOR_TIMEOUT();
+                callFrame->r(dst) = key;
+                vPC += target;
+                NEXT_INSTRUCTION();
+            }
         }
         }
-        it->invalidate();
 
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_next_pname);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jmp_scopes) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jmp_scopes) {
@@ -3593,8 +3650,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            specified by immediate number count, then jumps to offset
            target.
         */
            specified by immediate number count, then jumps to offset
            target.
         */
-        int count = (++vPC)->u.operand;
-        int target = (++vPC)->u.operand;
+        int count = vPC[1].u.operand;
+        int target = vPC[2].u.operand;
 
         ScopeChainNode* tmp = callFrame->scopeChain();
         while (count--)
 
         ScopeChainNode* tmp = callFrame->scopeChain();
         while (count--)
@@ -3617,7 +3674,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
          */
         callFrame->setScopeChain(createExceptionScope(callFrame, vPC));
 
          */
         callFrame->setScopeChain(createExceptionScope(callFrame, vPC));
 
-        vPC += 4;
+        vPC += OPCODE_LENGTH(op_push_new_scope);
         NEXT_INSTRUCTION();
     }
 #if HAVE(COMPUTED_GOTO)
         NEXT_INSTRUCTION();
     }
 #if HAVE(COMPUTED_GOTO)
@@ -3632,11 +3689,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         ASSERT(exceptionValue);
         ASSERT(!globalData->exception);
         */
         ASSERT(exceptionValue);
         ASSERT(!globalData->exception);
-        int ex = (++vPC)->u.operand;
+        int ex = vPC[1].u.operand;
         callFrame->r(ex) = exceptionValue;
         exceptionValue = JSValue();
 
         callFrame->r(ex) = exceptionValue;
         exceptionValue = JSValue();
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_catch);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_throw) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_throw) {
@@ -3650,7 +3707,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            else the script returns control to the nearest native caller.
         */
 
            else the script returns control to the nearest native caller.
         */
 
-        int ex = (++vPC)->u.operand;
+        int ex = vPC[1].u.operand;
         exceptionValue = callFrame->r(ex).jsValue();
 
         handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true);
         exceptionValue = callFrame->r(ex).jsValue();
 
         handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true);
@@ -3670,14 +3727,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            constant message as the message string. The result is
            written to register dst.
         */
            constant message as the message string. The result is
            written to register dst.
         */
-        int dst = (++vPC)->u.operand;
-        int type = (++vPC)->u.operand;
-        int message = (++vPC)->u.operand;
+        int dst = vPC[1].u.operand;
+        int type = vPC[2].u.operand;
+        int message = vPC[3].u.operand;
 
         CodeBlock* codeBlock = callFrame->codeBlock();
 
         CodeBlock* codeBlock = callFrame->codeBlock();
-        callFrame->r(dst) = JSValue(Error::create(callFrame, (ErrorType)type, callFrame->r(message).jsValue().toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()));
+        callFrame->r(dst) = JSValue(Error::create(callFrame, (ErrorType)type, callFrame->r(message).jsValue().toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()));
 
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_new_error);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_end) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_end) {
@@ -3692,7 +3749,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             ASSERT(scopeChain->refCount > 1);
             scopeChain->deref();
         }
             ASSERT(scopeChain->refCount > 1);
             scopeChain->deref();
         }
-        int result = (++vPC)->u.operand;
+        int result = vPC[1].u.operand;
         return callFrame->r(result).jsValue();
     }
     DEFINE_OPCODE(op_put_getter) {
         return callFrame->r(result).jsValue();
     }
     DEFINE_OPCODE(op_put_getter) {
@@ -3706,9 +3763,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Unlike many opcodes, this one does not write any output to
            the register file.
         */
            Unlike many opcodes, this one does not write any output to
            the register file.
         */
-        int base = (++vPC)->u.operand;
-        int property = (++vPC)->u.operand;
-        int function = (++vPC)->u.operand;
+        int base = vPC[1].u.operand;
+        int property = vPC[2].u.operand;
+        int function = vPC[3].u.operand;
 
         ASSERT(callFrame->r(base).jsValue().isObject());
         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
 
         ASSERT(callFrame->r(base).jsValue().isObject());
         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
@@ -3716,7 +3773,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         ASSERT(callFrame->r(function).jsValue().isObject());
         baseObj->defineGetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
 
         ASSERT(callFrame->r(function).jsValue().isObject());
         baseObj->defineGetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_put_getter);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_setter) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_setter) {
@@ -3730,17 +3787,17 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Unlike many opcodes, this one does not write any output to
            the register file.
         */
            Unlike many opcodes, this one does not write any output to
            the register file.
         */
-        int base = (++vPC)->u.operand;
-        int property = (++vPC)->u.operand;
-        int function = (++vPC)->u.operand;
+        int base = vPC[1].u.operand;
+        int property = vPC[2].u.operand;
+        int function = vPC[3].u.operand;
 
         ASSERT(callFrame->r(base).jsValue().isObject());
         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
         Identifier& ident = callFrame->codeBlock()->identifier(property);
         ASSERT(callFrame->r(function).jsValue().isObject());
 
         ASSERT(callFrame->r(base).jsValue().isObject());
         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
         Identifier& ident = callFrame->codeBlock()->identifier(property);
         ASSERT(callFrame->r(function).jsValue().isObject());
-        baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
+        baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()), 0);
 
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_put_setter);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_method_check) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_method_check) {
@@ -3753,9 +3810,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Places the address of the next instruction into the retAddrDst
            register and jumps to offset target from the current instruction.
         */
            Places the address of the next instruction into the retAddrDst
            register and jumps to offset target from the current instruction.
         */
-        int retAddrDst = (++vPC)->u.operand;
-        int target = (++vPC)->u.operand;
-        callFrame->r(retAddrDst) = vPC + 1;
+        int retAddrDst = vPC[1].u.operand;
+        int target = vPC[2].u.operand;
+        callFrame->r(retAddrDst) = vPC + OPCODE_LENGTH(op_jsr);
 
         vPC += target;
         NEXT_INSTRUCTION();
 
         vPC += target;
         NEXT_INSTRUCTION();
@@ -3767,7 +3824,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
          differs from op_jmp because the target address is stored in a
          register, not as an immediate.
         */
          differs from op_jmp because the target address is stored in a
          register, not as an immediate.
         */
-        int retAddrSrc = (++vPC)->u.operand;
+        int retAddrSrc = vPC[1].u.operand;
         vPC = callFrame->r(retAddrSrc).vPC();
         NEXT_INSTRUCTION();
     }
         vPC = callFrame->r(retAddrSrc).vPC();
         NEXT_INSTRUCTION();
     }
@@ -3777,13 +3834,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
          Notifies the debugger of the current state of execution. This opcode
          is only generated while the debugger is attached.
         */
          Notifies the debugger of the current state of execution. This opcode
          is only generated while the debugger is attached.
         */
-        int debugHookID = (++vPC)->u.operand;
-        int firstLine = (++vPC)->u.operand;
-        int lastLine = (++vPC)->u.operand;
+        int debugHookID = vPC[1].u.operand;
+        int firstLine = vPC[2].u.operand;
+        int lastLine = vPC[3].u.operand;
 
         debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
 
 
         debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
 
-        ++vPC;
+        vPC += OPCODE_LENGTH(op_debug);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_profile_will_call) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_profile_will_call) {
@@ -3797,7 +3854,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         if (*enabledProfilerReference)
             (*enabledProfilerReference)->willExecute(callFrame, callFrame->r(function).jsValue());
 
         if (*enabledProfilerReference)
             (*enabledProfilerReference)->willExecute(callFrame, callFrame->r(function).jsValue());
 
-        vPC += 2;
+        vPC += OPCODE_LENGTH(op_profile_will_call);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_profile_did_call) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_profile_did_call) {
@@ -3811,7 +3868,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         if (*enabledProfilerReference)
             (*enabledProfilerReference)->didExecute(callFrame, callFrame->r(function).jsValue());
 
         if (*enabledProfilerReference)
             (*enabledProfilerReference)->didExecute(callFrame, callFrame->r(function).jsValue());
 
-        vPC += 2;
+        vPC += OPCODE_LENGTH(op_profile_did_call);
         NEXT_INSTRUCTION();
     }
     vm_throw: {
         NEXT_INSTRUCTION();
     }
     vm_throw: {
@@ -3850,7 +3907,7 @@ JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* functio
     CodeBlock* codeBlock = functionCallFrame->codeBlock();
     if (codeBlock->usesArguments()) {
         ASSERT(codeBlock->codeType() == FunctionCode);
     CodeBlock* codeBlock = functionCallFrame->codeBlock();
     if (codeBlock->usesArguments()) {
         ASSERT(codeBlock->codeType() == FunctionCode);
-        SymbolTable& symbolTable = codeBlock->symbolTable();
+        SymbolTable& symbolTable = *codeBlock->symbolTable();
         int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex();
         if (!functionCallFrame->r(argumentsIndex).jsValue()) {
             Arguments* arguments = new (callFrame) Arguments(functionCallFrame);
         int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex();
         if (!functionCallFrame->r(argumentsIndex).jsValue()) {
             Arguments* arguments = new (callFrame) Arguments(functionCallFrame);
@@ -3903,8 +3960,8 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp
 
     unsigned bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC());
     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1);
 
     unsigned bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC());
     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1);
-    sourceID = callerCodeBlock->ownerNode()->sourceID();
-    sourceURL = callerCodeBlock->ownerNode()->sourceURL();
+    sourceID = callerCodeBlock->ownerExecutable()->sourceID();
+    sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
     function = callerFrame->callee();
 }
 
     function = callerFrame->callee();
 }
 
@@ -3917,4 +3974,40 @@ CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunc
     return 0;
 }
 
     return 0;
 }
 
+void Interpreter::enableSampler()
+{
+#if ENABLE(OPCODE_SAMPLING)
+    if (!m_sampler) {
+        m_sampler.set(new SamplingTool(this));
+        m_sampler->setup();
+    }
+#endif
+}
+void Interpreter::dumpSampleData(ExecState* exec)
+{
+#if ENABLE(OPCODE_SAMPLING)
+    if (m_sampler)
+        m_sampler->dump(exec);
+#else
+    UNUSED_PARAM(exec);
+#endif
+}
+void Interpreter::startSampling()
+{
+#if ENABLE(SAMPLING_THREAD)
+    if (!m_sampleEntryDepth)
+        SamplingThread::start();
+
+    m_sampleEntryDepth++;
+#endif
+}
+void Interpreter::stopSampling()
+{
+#if ENABLE(SAMPLING_THREAD)
+    m_sampleEntryDepth--;
+    if (!m_sampleEntryDepth)
+        SamplingThread::stop();
+#endif
+}
+
 } // namespace JSC
 } // namespace JSC
index f2047e411ccb7902a25a001a96fc884d22ee4ee4..5ddf58e658f119b84472ccabb38c0e3a84bd6eb6 100644 (file)
 
 #include "ArgList.h"
 #include "FastAllocBase.h"
 
 #include "ArgList.h"
 #include "FastAllocBase.h"
-#include "HashMap.h"
 #include "JSCell.h"
 #include "JSValue.h"
 #include "JSObject.h"
 #include "Opcode.h"
 #include "RegisterFile.h"
 
 #include "JSCell.h"
 #include "JSValue.h"
 #include "JSObject.h"
 #include "Opcode.h"
 #include "RegisterFile.h"
 
+#include <wtf/HashMap.h>
+
 namespace JSC {
 
     class CodeBlock;
 namespace JSC {
 
     class CodeBlock;
-    class EvalNode;
-    class FunctionBodyNode;
-    class Instruction;
+    class EvalExecutable;
+    class FunctionExecutable;
     class InternalFunction;
     class JSFunction;
     class JSGlobalObject;
     class InternalFunction;
     class JSFunction;
     class JSGlobalObject;
-    class ProgramNode;
+    class ProgramExecutable;
     class Register;
     class ScopeChainNode;
     class SamplingTool;
     struct CallFrameClosure;
     struct HandlerInfo;
     class Register;
     class ScopeChainNode;
     class SamplingTool;
     struct CallFrameClosure;
     struct HandlerInfo;
-
+    struct Instruction;
+    
     enum DebugHookID {
         WillExecuteProgram,
         DidExecuteProgram,
     enum DebugHookID {
         WillExecuteProgram,
         DidExecuteProgram,
@@ -96,9 +97,9 @@ namespace JSC {
 
         bool isOpcode(Opcode);
         
 
         bool isOpcode(Opcode);
         
-        JSValue execute(ProgramNode*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValue* exception);
-        JSValue execute(FunctionBodyNode*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue* exception);
-        JSValue execute(EvalNode* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception);
+        JSValue execute(ProgramExecutable*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValue* exception);
+        JSValue execute(FunctionExecutable*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue* exception);
+        JSValue execute(EvalExecutable* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception);
 
         JSValue retrieveArguments(CallFrame*, JSFunction*) const;
         JSValue retrieveCaller(CallFrame*, InternalFunction*) const;
 
         JSValue retrieveArguments(CallFrame*, JSFunction*) const;
         JSValue retrieveCaller(CallFrame*, InternalFunction*) const;
@@ -106,21 +107,23 @@ namespace JSC {
         
         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
         
         
         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
         
-        void setSampler(SamplingTool* sampler) { m_sampler = sampler; }
-        SamplingTool* sampler() { return m_sampler; }
+        SamplingTool* sampler() { return m_sampler.get(); }
 
         NEVER_INLINE JSValue callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValue& exceptionValue);
         NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset, bool);
         NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
 
 
         NEVER_INLINE JSValue callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValue& exceptionValue);
         NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset, bool);
         NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
 
+        void dumpSampleData(ExecState* exec);
+        void startSampling();
+        void stopSampling();
     private:
         enum ExecutionFlag { Normal, InitializeAndReturn };
 
     private:
         enum ExecutionFlag { Normal, InitializeAndReturn };
 
-        CallFrameClosure prepareForRepeatCall(FunctionBodyNode*, CallFrame*, JSFunction*, int argCount, ScopeChainNode*, JSValue* exception);
+        CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argCount, ScopeChainNode*, JSValue* exception);
         void endRepeatCall(CallFrameClosure&);
         JSValue execute(CallFrameClosure&, JSValue* exception);
 
         void endRepeatCall(CallFrameClosure&);
         JSValue execute(CallFrameClosure&, JSValue* exception);
 
-        JSValue execute(EvalNode*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue* exception);
+        JSValue execute(EvalExecutable*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue* exception);
 
 #if USE(INTERPRETER)
         NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
 
 #if USE(INTERPRETER)
         NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
@@ -128,7 +131,6 @@ namespace JSC {
         NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC);
         NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC);
         NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue);
-        NEVER_INLINE bool resolveBaseAndFunc(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC);
 
         void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const Identifier& propertyName, const PropertySlot&);
         NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC);
 
         void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const Identifier& propertyName, const PropertySlot&);
@@ -150,7 +152,9 @@ namespace JSC {
         
         bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
 
         
         bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
 
-        SamplingTool* m_sampler;
+        void enableSampler();
+        int m_sampleEntryDepth;
+        OwnPtr<SamplingTool> m_sampler;
 
         int m_reentryDepth;
 
 
         int m_reentryDepth;
 
index e1598122f6bbd0bf931a4dcfe7a9f9db1b5525ae..ecd7403246a2eb3952071392623a18766ded561e 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -55,9 +55,6 @@ namespace JSC {
         Register(const JSValue&);
         Register& operator=(const JSValue&);
         JSValue jsValue() const;
         Register(const JSValue&);
         Register& operator=(const JSValue&);
         JSValue jsValue() const;
-
-        bool marked() const;
-        void mark();
         
         Register& operator=(JSActivation*);
         Register& operator=(CallFrame*);
         
         Register& operator=(JSActivation*);
         Register& operator=(CallFrame*);
@@ -108,6 +105,9 @@ namespace JSC {
 
     ALWAYS_INLINE Register::Register(const JSValue& v)
     {
 
     ALWAYS_INLINE Register::Register(const JSValue& v)
     {
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!v.isZombie());
+#endif
         u.value = JSValue::encode(v);
     }
 
         u.value = JSValue::encode(v);
     }
 
@@ -124,17 +124,7 @@ namespace JSC {
     {
         return JSValue::decode(u.value);
     }
     {
         return JSValue::decode(u.value);
     }
-    
-    ALWAYS_INLINE bool Register::marked() const
-    {
-        return jsValue().marked();
-    }
 
 
-    ALWAYS_INLINE void Register::mark()
-    {
-        jsValue().mark();
-    }
-    
     // Interpreter functions
 
     ALWAYS_INLINE Register& Register::operator=(JSActivation* activation)
     // Interpreter functions
 
     ALWAYS_INLINE Register& Register::operator=(JSActivation* activation)
index cfcf1d36277b3d5b06c7b6daf09ee3aeefe80abb..510effe0dd6c09a83584dc748969412823c52a17 100644 (file)
@@ -36,9 +36,12 @@ RegisterFile::~RegisterFile()
 #if HAVE(MMAP)
     munmap(m_buffer, ((m_max - m_start) + m_maxGlobals) * sizeof(Register));
 #elif HAVE(VIRTUALALLOC)
 #if HAVE(MMAP)
     munmap(m_buffer, ((m_max - m_start) + m_maxGlobals) * sizeof(Register));
 #elif HAVE(VIRTUALALLOC)
+#if OS(WINCE)
+    VirtualFree(m_buffer, DWORD(m_commitEnd) - DWORD(m_buffer), MEM_DECOMMIT);
+#endif
     VirtualFree(m_buffer, 0, MEM_RELEASE);
 #else
     VirtualFree(m_buffer, 0, MEM_RELEASE);
 #else
-    #error "Don't know how to release virtual memory on this platform."
+    fastFree(m_buffer);
 #endif
 }
 
 #endif
 }
 
index 3a6e63b9e973a9943544dc46c18c5610062cb977..1fc4f828b48acc1b1a4772b00729882006ad23e3 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "Collector.h"
 #include "ExecutableAllocator.h"
 #include "Register.h"
 #include "Collector.h"
 #include "ExecutableAllocator.h"
 #include "Register.h"
+#include <stdio.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/VMTags.h>
 
 #if HAVE(MMAP)
 #include <errno.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/VMTags.h>
 
 #if HAVE(MMAP)
 #include <errno.h>
-#include <stdio.h>
 #include <sys/mman.h>
 #endif
 
 #include <sys/mman.h>
 #endif
 
@@ -92,7 +92,7 @@ namespace JSC {
 
     class JSGlobalObject;
 
 
     class JSGlobalObject;
 
-    class RegisterFile : Noncopyable {
+    class RegisterFile : public Noncopyable {
         friend class JIT;
     public:
         enum CallFrameHeaderEntry {
         friend class JIT;
     public:
         enum CallFrameHeaderEntry {
@@ -136,8 +136,8 @@ namespace JSC {
 
         Register* lastGlobal() const { return m_start - m_numGlobals; }
         
 
         Register* lastGlobal() const { return m_start - m_numGlobals; }
         
-        void markGlobals(Heap* heap) { heap->markConservatively(lastGlobal(), m_start); }
-        void markCallFrames(Heap* heap) { heap->markConservatively(m_start, m_end); }
+        void markGlobals(MarkStack& markStack, Heap* heap) { heap->markConservatively(markStack, lastGlobal(), m_start); }
+        void markCallFrames(MarkStack& markStack, Heap* heap) { heap->markConservatively(markStack, m_start, m_end); }
 
     private:
         void releaseExcessCapacity();
 
     private:
         void releaseExcessCapacity();
@@ -176,7 +176,7 @@ namespace JSC {
     #if HAVE(MMAP)
         m_buffer = static_cast<Register*>(mmap(0, bufferLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, VM_TAG_FOR_REGISTERFILE_MEMORY, 0));
         if (m_buffer == MAP_FAILED) {
     #if HAVE(MMAP)
         m_buffer = static_cast<Register*>(mmap(0, bufferLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, VM_TAG_FOR_REGISTERFILE_MEMORY, 0));
         if (m_buffer == MAP_FAILED) {
-#if PLATFORM(WINCE)
+#if OS(WINCE)
             fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
 #else
             fprintf(stderr, "Could not allocate register file: %d\n", errno);
             fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
 #else
             fprintf(stderr, "Could not allocate register file: %d\n", errno);
@@ -186,7 +186,7 @@ namespace JSC {
     #elif HAVE(VIRTUALALLOC)
         m_buffer = static_cast<Register*>(VirtualAlloc(0, roundUpAllocationSize(bufferLength, commitSize), MEM_RESERVE, PAGE_READWRITE));
         if (!m_buffer) {
     #elif HAVE(VIRTUALALLOC)
         m_buffer = static_cast<Register*>(VirtualAlloc(0, roundUpAllocationSize(bufferLength, commitSize), MEM_RESERVE, PAGE_READWRITE));
         if (!m_buffer) {
-#if PLATFORM(WINCE)
+#if OS(WINCE)
             fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
 #else
             fprintf(stderr, "Could not allocate register file: %d\n", errno);
             fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
 #else
             fprintf(stderr, "Could not allocate register file: %d\n", errno);
@@ -196,7 +196,7 @@ namespace JSC {
         size_t committedSize = roundUpAllocationSize(maxGlobals * sizeof(Register), commitSize);
         void* commitCheck = VirtualAlloc(m_buffer, committedSize, MEM_COMMIT, PAGE_READWRITE);
         if (commitCheck != m_buffer) {
         size_t committedSize = roundUpAllocationSize(maxGlobals * sizeof(Register), commitSize);
         void* commitCheck = VirtualAlloc(m_buffer, committedSize, MEM_COMMIT, PAGE_READWRITE);
         if (commitCheck != m_buffer) {
-#if PLATFORM(WINCE)
+#if OS(WINCE)
             fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
 #else
             fprintf(stderr, "Could not allocate register file: %d\n", errno);
             fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
 #else
             fprintf(stderr, "Could not allocate register file: %d\n", errno);
@@ -204,8 +204,16 @@ namespace JSC {
             CRASH();
         }
         m_commitEnd = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_buffer) + committedSize);
             CRASH();
         }
         m_commitEnd = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_buffer) + committedSize);
-    #else
-        #error "Don't know how to reserve virtual memory on this platform."
+    #else 
+        /* 
+         * If neither MMAP nor VIRTUALALLOC are available - use fastMalloc instead.
+         *
+         * Please note that this is the fallback case, which is non-optimal.
+         * If any possible, the platform should provide for a better memory
+         * allocation mechanism that allows for "lazy commit" or dynamic
+         * pre-allocation, similar to mmap or VirtualAlloc, to avoid waste of memory.
+         */
+        m_buffer = static_cast<Register*>(fastMalloc(bufferLength));
     #endif
         m_start = m_buffer + maxGlobals;
         m_end = m_start;
     #endif
         m_start = m_buffer + maxGlobals;
         m_end = m_start;
@@ -234,7 +242,7 @@ namespace JSC {
         if (newEnd > m_commitEnd) {
             size_t size = roundUpAllocationSize(reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_commitEnd), commitSize);
             if (!VirtualAlloc(m_commitEnd, size, MEM_COMMIT, PAGE_READWRITE)) {
         if (newEnd > m_commitEnd) {
             size_t size = roundUpAllocationSize(reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_commitEnd), commitSize);
             if (!VirtualAlloc(m_commitEnd, size, MEM_COMMIT, PAGE_READWRITE)) {
-#if PLATFORM(WINCE)
+#if OS(WINCE)
                 fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
 #else
                 fprintf(stderr, "Could not allocate register file: %d\n", errno);
                 fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
 #else
                 fprintf(stderr, "Could not allocate register file: %d\n", errno);
index 5223bf38fcd7f7f5aa1e126e52783afe08ab4b94..1fb8ff744b544b4c9575e882a599b404cd9ab489 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef ExecutableAllocator_h
 #define ExecutableAllocator_h
 
 #ifndef ExecutableAllocator_h
 #define ExecutableAllocator_h
 
+#include <stddef.h> // for ptrdiff_t
 #include <limits>
 #include <wtf/Assertions.h>
 #include <wtf/PassRefPtr.h>
 #include <limits>
 #include <wtf/Assertions.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/UnusedParam.h>
 #include <wtf/Vector.h>
 
 #include <wtf/UnusedParam.h>
 #include <wtf/Vector.h>
 
+#if OS(IPHONE_OS)
 #include <libkern/OSCacheControl.h>
 #include <sys/mman.h>
 #include <libkern/OSCacheControl.h>
 #include <sys/mman.h>
+#endif
+
+#if OS(SYMBIAN)
+#include <e32std.h>
+#endif
+
+#if OS(WINCE)
+// From pkfuncs.h (private header file from the Platform Builder)
+#define CACHE_SYNC_ALL 0x07F
+extern "C" __declspec(dllimport) void CacheRangeFlush(LPVOID pAddr, DWORD dwLength, DWORD dwFlags);
+#endif
 
 #define JIT_ALLOCATOR_PAGE_SIZE (ExecutableAllocator::pageSize)
 #define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (ExecutableAllocator::pageSize * 4)
 
 #define JIT_ALLOCATOR_PAGE_SIZE (ExecutableAllocator::pageSize)
 #define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (ExecutableAllocator::pageSize * 4)
@@ -72,6 +85,9 @@ private:
     struct Allocation {
         char* pages;
         size_t size;
     struct Allocation {
         char* pages;
         size_t size;
+#if OS(SYMBIAN)
+        RChunk* chunk;
+#endif
     };
     typedef Vector<Allocation, 2> AllocationList;
 
     };
     typedef Vector<Allocation, 2> AllocationList;
 
@@ -170,18 +186,60 @@ public:
 #endif
 
 
 #endif
 
 
-#if PLATFORM(X86) || PLATFORM(X86_64)
+#if CPU(X86) || CPU(X86_64)
     static void cacheFlush(void*, size_t)
     {
     }
     static void cacheFlush(void*, size_t)
     {
     }
-#elif PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE)
+#elif CPU(ARM_THUMB2) && OS(IPHONE_OS)
     static void cacheFlush(void* code, size_t size)
     {
         sys_dcache_flush(code, size);
         sys_icache_invalidate(code, size);
     }
     static void cacheFlush(void* code, size_t size)
     {
         sys_dcache_flush(code, size);
         sys_icache_invalidate(code, size);
     }
+#elif CPU(ARM_THUMB2) && OS(LINUX)
+    static void cacheFlush(void* code, size_t size)
+    {
+        asm volatile (
+            "push    {r7}\n"
+            "mov     r0, %0\n"
+            "mov     r1, %1\n"
+            "movw    r7, #0x2\n"
+            "movt    r7, #0xf\n"
+            "movs    r2, #0x0\n"
+            "svc     0x0\n"
+            "pop     {r7}\n"
+            :
+            : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
+            : "r0", "r1", "r2");
+    }
+#elif OS(SYMBIAN)
+    static void cacheFlush(void* code, size_t size)
+    {
+        User::IMB_Range(code, static_cast<char*>(code) + size);
+    }
+#elif CPU(ARM_TRADITIONAL) && OS(LINUX)
+    static void cacheFlush(void* code, size_t size)
+    {
+        asm volatile (
+            "push    {r7}\n"
+            "mov     r0, %0\n"
+            "mov     r1, %1\n"
+            "mov     r7, #0xf0000\n"
+            "add     r7, r7, #0x2\n"
+            "mov     r2, #0x0\n"
+            "svc     0x0\n"
+            "pop     {r7}\n"
+            :
+            : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
+            : "r0", "r1", "r2");
+    }
+#elif OS(WINCE)
+    static void cacheFlush(void* code, size_t size)
+    {
+        CacheRangeFlush(code, size, CACHE_SYNC_ALL);
+    }
 #else
 #else
-#error "ExecutableAllocator::cacheFlush not implemented on this platform."
+    #error "The cacheFlush support is missing on this platform."
 #endif
 
 private:
 #endif
 
 private:
@@ -225,6 +283,7 @@ inline void* ExecutablePool::poolAllocate(size_t n)
 }
 
 }
 }
 
 }
+
 #endif // ENABLE(ASSEMBLER)
 
 #endif // !defined(ExecutableAllocator)
 #endif // ENABLE(ASSEMBLER)
 
 #endif // !defined(ExecutableAllocator)
index 7682b9c6421a6b4518f4eea92f599db02af37574..dd1db4e24ab85df7d8ff8e7c22d89489af8b4918 100644 (file)
@@ -29,7 +29,7 @@
 
 #include <errno.h>
 
 
 #include <errno.h>
 
-#if ENABLE(ASSEMBLER) && PLATFORM(MAC) && PLATFORM(X86_64)
+#if ENABLE(ASSEMBLER) && OS(DARWIN) && CPU(X86_64)
 
 #include "TCSpinLock.h"
 #include <mach/mach_init.h>
 
 #include "TCSpinLock.h"
 #include <mach/mach_init.h>
index 4bd5a2c6e90eef766ccfb7999bf4f6a60e51d48d..06375adb537f2ed0713118e58dae761772de9676 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "ExecutableAllocator.h"
 
 
 #include "ExecutableAllocator.h"
 
-#if ENABLE(ASSEMBLER)
+#if ENABLE(ASSEMBLER) && OS(UNIX) && !OS(SYMBIAN)
 
 #include <sys/mman.h>
 #include <unistd.h>
 
 #include <sys/mman.h>
 #include <unistd.h>
@@ -35,7 +35,7 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
-#if !(PLATFORM(MAC) && PLATFORM(X86_64))
+#if !(OS(DARWIN) && CPU(X86_64))
 
 void ExecutableAllocator::intializePageSize()
 {
 
 void ExecutableAllocator::intializePageSize()
 {
@@ -44,7 +44,10 @@ void ExecutableAllocator::intializePageSize()
 
 ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
 {
 
 ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
 {
-    ExecutablePool::Allocation alloc = { reinterpret_cast<char*>(mmap(NULL, n, INITIAL_PROTECTION_FLAGS, MAP_PRIVATE | MAP_ANON, VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY, 0)), n };
+    void* allocation = mmap(NULL, n, INITIAL_PROTECTION_FLAGS, MAP_PRIVATE | MAP_ANON, VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY, 0);
+    if (allocation == MAP_FAILED)
+        CRASH();
+    ExecutablePool::Allocation alloc = { reinterpret_cast<char*>(allocation), n };
     return alloc;
 }
 
     return alloc;
 }
 
@@ -54,7 +57,7 @@ void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
     ASSERT_UNUSED(result, !result);
 }
 
     ASSERT_UNUSED(result, !result);
 }
 
-#endif // !(PLATFORM(MAC) && PLATFORM(X86_64))
+#endif // !(OS(DARWIN) && CPU(X86_64))
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
 void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSeting setting)
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
 void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSeting setting)
diff --git a/jit/ExecutableAllocatorSymbian.cpp b/jit/ExecutableAllocatorSymbian.cpp
new file mode 100644 (file)
index 0000000..e82975c
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ *  Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+
+#include "ExecutableAllocator.h"
+
+#if ENABLE(ASSEMBLER) && OS(SYMBIAN)
+
+#include <e32hal.h>
+#include <e32std.h>
+
+// Set the page size to 256 Kb to compensate for moving memory model limitation
+const size_t MOVING_MEM_PAGE_SIZE = 256 * 1024; 
+
+namespace JSC {
+
+void ExecutableAllocator::intializePageSize()
+{
+#if CPU(ARMV5_OR_LOWER)
+    // The moving memory model (as used in ARMv5 and earlier platforms)
+    // on Symbian OS limits the number of chunks for each process to 16. 
+    // To mitigate this limitation increase the pagesize to 
+    // allocate less of larger chunks.
+    ExecutableAllocator::pageSize = MOVING_MEM_PAGE_SIZE;
+#else
+    TInt page_size;
+    UserHal::PageSizeInBytes(page_size);
+    ExecutableAllocator::pageSize = page_size;
+#endif
+}
+
+ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
+{
+    RChunk* codeChunk = new RChunk();
+
+    TInt errorCode = codeChunk->CreateLocalCode(n, n);
+
+    char* allocation = reinterpret_cast<char*>(codeChunk->Base());
+    if (!allocation)
+        CRASH();
+    ExecutablePool::Allocation alloc = { allocation, n, codeChunk };
+    return alloc;
+}
+
+void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
+{ 
+    alloc.chunk->Close();
+    delete alloc.chunk;
+}
+
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+#error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform."
+#endif
+
+}
+
+#endif // HAVE(ASSEMBLER)
index a9ba7d0ea1bc2e52311c4feea19e33d90dc518f5..e38323c5fddd394628cd0d8fe6842a6c53c479c5 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "ExecutableAllocator.h"
 
 
 #include "ExecutableAllocator.h"
 
-#if ENABLE(ASSEMBLER)
+#if ENABLE(ASSEMBLER) && OS(WINDOWS)
 
 #include "windows.h"
 
 
 #include "windows.h"
 
@@ -42,7 +42,10 @@ void ExecutableAllocator::intializePageSize()
 
 ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
 {
 
 ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
 {
-    ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(VirtualAlloc(0, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)), n};
+    void* allocation = VirtualAlloc(0, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+    if (!allocation)
+        CRASH();
+    ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(allocation), n};
     return alloc;
 }
 
     return alloc;
 }
 
index 74d7312317690d80e0416fb1de918d74765ef000..c0da66df595eaf4914858fd3f4f25d6f1b9adcc9 100644 (file)
@@ -27,7 +27,7 @@
 #include "JIT.h"
 
 // This probably does not belong here; adding here for now as a quick Windows build fix.
 #include "JIT.h"
 
 // This probably does not belong here; adding here for now as a quick Windows build fix.
-#if ENABLE(ASSEMBLER) && PLATFORM(X86) && !PLATFORM(MAC)
+#if ENABLE(ASSEMBLER) && CPU(X86) && !OS(MAC_OS_X)
 #include "MacroAssembler.h"
 JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2;
 #endif
 #include "MacroAssembler.h"
 JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2;
 #endif
@@ -37,7 +37,6 @@ JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse
 #include "CodeBlock.h"
 #include "Interpreter.h"
 #include "JITInlineMethods.h"
 #include "CodeBlock.h"
 #include "Interpreter.h"
 #include "JITInlineMethods.h"
-#include "JITStubs.h"
 #include "JITStubCall.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JITStubCall.h"
 #include "JSArray.h"
 #include "JSFunction.h"
@@ -195,14 +194,13 @@ void JIT::privateCompileMainPass()
 
         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
         DEFINE_BINARY_OP(op_del_by_val)
 
         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
         DEFINE_BINARY_OP(op_del_by_val)
-#if !USE(JSVALUE32_64)
+#if USE(JSVALUE32)
         DEFINE_BINARY_OP(op_div)
 #endif
         DEFINE_BINARY_OP(op_in)
         DEFINE_BINARY_OP(op_less)
         DEFINE_BINARY_OP(op_lesseq)
         DEFINE_BINARY_OP(op_urshift)
         DEFINE_BINARY_OP(op_div)
 #endif
         DEFINE_BINARY_OP(op_in)
         DEFINE_BINARY_OP(op_less)
         DEFINE_BINARY_OP(op_lesseq)
         DEFINE_BINARY_OP(op_urshift)
-        DEFINE_UNARY_OP(op_get_pnames)
         DEFINE_UNARY_OP(op_is_boolean)
         DEFINE_UNARY_OP(op_is_function)
         DEFINE_UNARY_OP(op_is_number)
         DEFINE_UNARY_OP(op_is_boolean)
         DEFINE_UNARY_OP(op_is_function)
         DEFINE_UNARY_OP(op_is_number)
@@ -230,7 +228,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_create_arguments)
         DEFINE_OP(op_debug)
         DEFINE_OP(op_del_by_id)
         DEFINE_OP(op_create_arguments)
         DEFINE_OP(op_debug)
         DEFINE_OP(op_del_by_id)
-#if USE(JSVALUE32_64)
+#if !USE(JSVALUE32)
         DEFINE_OP(op_div)
 #endif
         DEFINE_OP(op_end)
         DEFINE_OP(op_div)
 #endif
         DEFINE_OP(op_end)
@@ -240,7 +238,9 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_eq_null)
         DEFINE_OP(op_get_by_id)
         DEFINE_OP(op_get_by_val)
         DEFINE_OP(op_eq_null)
         DEFINE_OP(op_get_by_id)
         DEFINE_OP(op_get_by_val)
+        DEFINE_OP(op_get_by_pname)
         DEFINE_OP(op_get_global_var)
         DEFINE_OP(op_get_global_var)
+        DEFINE_OP(op_get_pnames)
         DEFINE_OP(op_get_scoped_var)
         DEFINE_OP(op_instanceof)
         DEFINE_OP(op_jeq_null)
         DEFINE_OP(op_get_scoped_var)
         DEFINE_OP(op_instanceof)
         DEFINE_OP(op_jeq_null)
@@ -250,6 +250,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_jneq_null)
         DEFINE_OP(op_jneq_ptr)
         DEFINE_OP(op_jnless)
         DEFINE_OP(op_jneq_null)
         DEFINE_OP(op_jneq_ptr)
         DEFINE_OP(op_jnless)
+        DEFINE_OP(op_jless)
         DEFINE_OP(op_jnlesseq)
         DEFINE_OP(op_jsr)
         DEFINE_OP(op_jtrue)
         DEFINE_OP(op_jnlesseq)
         DEFINE_OP(op_jsr)
         DEFINE_OP(op_jtrue)
@@ -258,6 +259,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_loop_if_less)
         DEFINE_OP(op_loop_if_lesseq)
         DEFINE_OP(op_loop_if_true)
         DEFINE_OP(op_loop_if_less)
         DEFINE_OP(op_loop_if_lesseq)
         DEFINE_OP(op_loop_if_true)
+        DEFINE_OP(op_loop_if_false)
         DEFINE_OP(op_lshift)
         DEFINE_OP(op_method_check)
         DEFINE_OP(op_mod)
         DEFINE_OP(op_lshift)
         DEFINE_OP(op_method_check)
         DEFINE_OP(op_mod)
@@ -379,20 +381,23 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_OP(op_construct)
         DEFINE_SLOWCASE_OP(op_construct_verify)
         DEFINE_SLOWCASE_OP(op_convert_this)
         DEFINE_SLOWCASE_OP(op_construct)
         DEFINE_SLOWCASE_OP(op_construct_verify)
         DEFINE_SLOWCASE_OP(op_convert_this)
-#if USE(JSVALUE32_64)
+#if !USE(JSVALUE32)
         DEFINE_SLOWCASE_OP(op_div)
 #endif
         DEFINE_SLOWCASE_OP(op_eq)
         DEFINE_SLOWCASE_OP(op_get_by_id)
         DEFINE_SLOWCASE_OP(op_get_by_val)
         DEFINE_SLOWCASE_OP(op_div)
 #endif
         DEFINE_SLOWCASE_OP(op_eq)
         DEFINE_SLOWCASE_OP(op_get_by_id)
         DEFINE_SLOWCASE_OP(op_get_by_val)
+        DEFINE_SLOWCASE_OP(op_get_by_pname)
         DEFINE_SLOWCASE_OP(op_instanceof)
         DEFINE_SLOWCASE_OP(op_jfalse)
         DEFINE_SLOWCASE_OP(op_jnless)
         DEFINE_SLOWCASE_OP(op_instanceof)
         DEFINE_SLOWCASE_OP(op_jfalse)
         DEFINE_SLOWCASE_OP(op_jnless)
+        DEFINE_SLOWCASE_OP(op_jless)
         DEFINE_SLOWCASE_OP(op_jnlesseq)
         DEFINE_SLOWCASE_OP(op_jtrue)
         DEFINE_SLOWCASE_OP(op_loop_if_less)
         DEFINE_SLOWCASE_OP(op_loop_if_lesseq)
         DEFINE_SLOWCASE_OP(op_loop_if_true)
         DEFINE_SLOWCASE_OP(op_jnlesseq)
         DEFINE_SLOWCASE_OP(op_jtrue)
         DEFINE_SLOWCASE_OP(op_loop_if_less)
         DEFINE_SLOWCASE_OP(op_loop_if_lesseq)
         DEFINE_SLOWCASE_OP(op_loop_if_true)
+        DEFINE_SLOWCASE_OP(op_loop_if_false)
         DEFINE_SLOWCASE_OP(op_lshift)
         DEFINE_SLOWCASE_OP(op_method_check)
         DEFINE_SLOWCASE_OP(op_mod)
         DEFINE_SLOWCASE_OP(op_lshift)
         DEFINE_SLOWCASE_OP(op_method_check)
         DEFINE_SLOWCASE_OP(op_mod)
@@ -438,7 +443,7 @@ void JIT::privateCompileSlowCases()
 #endif
 }
 
 #endif
 }
 
-void JIT::privateCompile()
+JITCode JIT::privateCompile()
 {
     sampleCodeBlock(m_codeBlock);
 #if ENABLE(OPCODE_SAMPLING)
 {
     sampleCodeBlock(m_codeBlock);
 #if ENABLE(OPCODE_SAMPLING)
@@ -489,21 +494,21 @@ void JIT::privateCompile()
             ASSERT(record.type == SwitchRecord::Immediate || record.type == SwitchRecord::Character); 
             ASSERT(record.jumpTable.simpleJumpTable->branchOffsets.size() == record.jumpTable.simpleJumpTable->ctiOffsets.size());
 
             ASSERT(record.type == SwitchRecord::Immediate || record.type == SwitchRecord::Character); 
             ASSERT(record.jumpTable.simpleJumpTable->branchOffsets.size() == record.jumpTable.simpleJumpTable->ctiOffsets.size());
 
-            record.jumpTable.simpleJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + 3 + record.defaultOffset]);
+            record.jumpTable.simpleJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + record.defaultOffset]);
 
             for (unsigned j = 0; j < record.jumpTable.simpleJumpTable->branchOffsets.size(); ++j) {
                 unsigned offset = record.jumpTable.simpleJumpTable->branchOffsets[j];
 
             for (unsigned j = 0; j < record.jumpTable.simpleJumpTable->branchOffsets.size(); ++j) {
                 unsigned offset = record.jumpTable.simpleJumpTable->branchOffsets[j];
-                record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.simpleJumpTable->ctiDefault;
+                record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + offset]) : record.jumpTable.simpleJumpTable->ctiDefault;
             }
         } else {
             ASSERT(record.type == SwitchRecord::String);
 
             }
         } else {
             ASSERT(record.type == SwitchRecord::String);
 
-            record.jumpTable.stringJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + 3 + record.defaultOffset]);
+            record.jumpTable.stringJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + record.defaultOffset]);
 
             StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end();            
             for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) {
                 unsigned offset = it->second.branchOffset;
 
             StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end();            
             for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) {
                 unsigned offset = it->second.branchOffset;
-                it->second.ctiOffset = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.stringJumpTable->ctiDefault;
+                it->second.ctiOffset = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + offset]) : record.jumpTable.stringJumpTable->ctiDefault;
             }
         }
     }
             }
         }
     }
@@ -552,7 +557,7 @@ void JIT::privateCompile()
         info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
     }
 
         info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
     }
 
-    m_codeBlock->setJITCode(patchBuffer.finalizeCode());
+    return patchBuffer.finalizeCode();
 }
 
 #if !USE(JSVALUE32_64)
 }
 
 #if !USE(JSVALUE32_64)
@@ -577,7 +582,7 @@ void JIT::unlinkCall(CallLinkInfo* callLinkInfo)
     // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid
     // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive
     // match).  Reset the check so it no longer matches.
     // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid
     // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive
     // match).  Reset the check so it no longer matches.
-    RepatchBuffer repatchBuffer(callLinkInfo->ownerCodeBlock);
+    RepatchBuffer repatchBuffer(callLinkInfo->ownerCodeBlock.get());
 #if USE(JSVALUE32_64)
     repatchBuffer.repatch(callLinkInfo->hotPathBegin, 0);
 #else
 #if USE(JSVALUE32_64)
     repatchBuffer.repatch(callLinkInfo->hotPathBegin, 0);
 #else
@@ -587,12 +592,11 @@ void JIT::unlinkCall(CallLinkInfo* callLinkInfo)
 
 void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JITCode& code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData)
 {
 
 void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JITCode& code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData)
 {
-    ASSERT(calleeCodeBlock);
     RepatchBuffer repatchBuffer(callerCodeBlock);
 
     // Currently we only link calls with the exact number of arguments.
     // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant
     RepatchBuffer repatchBuffer(callerCodeBlock);
 
     // Currently we only link calls with the exact number of arguments.
     // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant
-    if (callerArgCount == calleeCodeBlock->m_numParameters || calleeCodeBlock->codeType() == NativeCode) {
+    if (!calleeCodeBlock || (callerArgCount == calleeCodeBlock->m_numParameters)) {
         ASSERT(!callLinkInfo->isLinked());
     
         if (calleeCodeBlock)
         ASSERT(!callLinkInfo->isLinked());
     
         if (calleeCodeBlock)
index 040f842e3d2078829b7ff38622aa77f4c07023f2..8e0c9acd5260af7f07d6d4ec1910088983ae5474 100644 (file)
--- a/jit/JIT.h
+++ b/jit/JIT.h
@@ -38,6 +38,8 @@
 #define JIT_CLASS_ALIGNMENT
 #endif
 
 #define JIT_CLASS_ALIGNMENT
 #endif
 
+#define ASSERT_JIT_OFFSET(actual, expected) ASSERT_WITH_MESSAGE(actual == expected, "JIT Offset \"%s\" should be %d, not %d.\n", #expected, static_cast<int>(actual), static_cast<int>(expected));
+
 #include "CodeBlock.h"
 #include "Interpreter.h"
 #include "JITCode.h"
 #include "CodeBlock.h"
 #include "Interpreter.h"
 #include "JITCode.h"
@@ -59,14 +61,14 @@ namespace JSC {
     class Register;
     class RegisterFile;
     class ScopeChainNode;
     class Register;
     class RegisterFile;
     class ScopeChainNode;
-    class SimpleJumpTable;
-    class StringJumpTable;
     class StructureChain;
 
     struct CallLinkInfo;
     struct Instruction;
     struct OperandTypes;
     struct PolymorphicAccessStructureList;
     class StructureChain;
 
     struct CallLinkInfo;
     struct Instruction;
     struct OperandTypes;
     struct PolymorphicAccessStructureList;
+    struct SimpleJumpTable;
+    struct StringJumpTable;
     struct StructureStubInfo;
 
     struct CallRecord {
     struct StructureStubInfo;
 
     struct CallRecord {
@@ -190,58 +192,82 @@ namespace JSC {
         // on x86/x86-64 it is ecx for performance reasons, since the
         // MacroAssembler will need to plant register swaps if it is not -
         // however the code will still function correctly.
         // on x86/x86-64 it is ecx for performance reasons, since the
         // MacroAssembler will need to plant register swaps if it is not -
         // however the code will still function correctly.
-#if PLATFORM(X86_64)
-        static const RegisterID returnValueRegister = X86::eax;
-        static const RegisterID cachedResultRegister = X86::eax;
-        static const RegisterID firstArgumentRegister = X86::edi;
-
-        static const RegisterID timeoutCheckRegister = X86::r12;
-        static const RegisterID callFrameRegister = X86::r13;
-        static const RegisterID tagTypeNumberRegister = X86::r14;
-        static const RegisterID tagMaskRegister = X86::r15;
-
-        static const RegisterID regT0 = X86::eax;
-        static const RegisterID regT1 = X86::edx;
-        static const RegisterID regT2 = X86::ecx;
-        static const RegisterID regT3 = X86::ebx;
-
-        static const FPRegisterID fpRegT0 = X86::xmm0;
-        static const FPRegisterID fpRegT1 = X86::xmm1;
-        static const FPRegisterID fpRegT2 = X86::xmm2;
-#elif PLATFORM(X86)
-        static const RegisterID returnValueRegister = X86::eax;
-        static const RegisterID cachedResultRegister = X86::eax;
+#if CPU(X86_64)
+        static const RegisterID returnValueRegister = X86Registers::eax;
+        static const RegisterID cachedResultRegister = X86Registers::eax;
+        static const RegisterID firstArgumentRegister = X86Registers::edi;
+
+        static const RegisterID timeoutCheckRegister = X86Registers::r12;
+        static const RegisterID callFrameRegister = X86Registers::r13;
+        static const RegisterID tagTypeNumberRegister = X86Registers::r14;
+        static const RegisterID tagMaskRegister = X86Registers::r15;
+
+        static const RegisterID regT0 = X86Registers::eax;
+        static const RegisterID regT1 = X86Registers::edx;
+        static const RegisterID regT2 = X86Registers::ecx;
+        static const RegisterID regT3 = X86Registers::ebx;
+
+        static const FPRegisterID fpRegT0 = X86Registers::xmm0;
+        static const FPRegisterID fpRegT1 = X86Registers::xmm1;
+        static const FPRegisterID fpRegT2 = X86Registers::xmm2;
+#elif CPU(X86)
+        static const RegisterID returnValueRegister = X86Registers::eax;
+        static const RegisterID cachedResultRegister = X86Registers::eax;
         // On x86 we always use fastcall conventions = but on
         // OS X if might make more sense to just use regparm.
         // On x86 we always use fastcall conventions = but on
         // OS X if might make more sense to just use regparm.
-        static const RegisterID firstArgumentRegister = X86::ecx;
-
-        static const RegisterID timeoutCheckRegister = X86::esi;
-        static const RegisterID callFrameRegister = X86::edi;
-
-        static const RegisterID regT0 = X86::eax;
-        static const RegisterID regT1 = X86::edx;
-        static const RegisterID regT2 = X86::ecx;
-        static const RegisterID regT3 = X86::ebx;
-
-        static const FPRegisterID fpRegT0 = X86::xmm0;
-        static const FPRegisterID fpRegT1 = X86::xmm1;
-        static const FPRegisterID fpRegT2 = X86::xmm2;
-#elif PLATFORM_ARM_ARCH(7)
-        static const RegisterID returnValueRegister = ARM::r0;
-        static const RegisterID cachedResultRegister = ARM::r0;
-        static const RegisterID firstArgumentRegister = ARM::r0;
-
-        static const RegisterID regT0 = ARM::r0;
-        static const RegisterID regT1 = ARM::r1;
-        static const RegisterID regT2 = ARM::r2;
-        static const RegisterID regT3 = ARM::r4;
-
-        static const RegisterID callFrameRegister = ARM::r5;
-        static const RegisterID timeoutCheckRegister = ARM::r6;
-
-        static const FPRegisterID fpRegT0 = ARM::d0;
-        static const FPRegisterID fpRegT1 = ARM::d1;
-        static const FPRegisterID fpRegT2 = ARM::d2;
+        static const RegisterID firstArgumentRegister = X86Registers::ecx;
+
+        static const RegisterID timeoutCheckRegister = X86Registers::esi;
+        static const RegisterID callFrameRegister = X86Registers::edi;
+
+        static const RegisterID regT0 = X86Registers::eax;
+        static const RegisterID regT1 = X86Registers::edx;
+        static const RegisterID regT2 = X86Registers::ecx;
+        static const RegisterID regT3 = X86Registers::ebx;
+
+        static const FPRegisterID fpRegT0 = X86Registers::xmm0;
+        static const FPRegisterID fpRegT1 = X86Registers::xmm1;
+        static const FPRegisterID fpRegT2 = X86Registers::xmm2;
+#elif CPU(ARM_THUMB2)
+        static const RegisterID returnValueRegister = ARMRegisters::r0;
+        static const RegisterID cachedResultRegister = ARMRegisters::r0;
+        static const RegisterID firstArgumentRegister = ARMRegisters::r0;
+
+        static const RegisterID regT0 = ARMRegisters::r0;
+        static const RegisterID regT1 = ARMRegisters::r1;
+        static const RegisterID regT2 = ARMRegisters::r2;
+        static const RegisterID regT3 = ARMRegisters::r4;
+
+        static const RegisterID callFrameRegister = ARMRegisters::r5;
+        static const RegisterID timeoutCheckRegister = ARMRegisters::r6;
+
+        static const FPRegisterID fpRegT0 = ARMRegisters::d0;
+        static const FPRegisterID fpRegT1 = ARMRegisters::d1;
+        static const FPRegisterID fpRegT2 = ARMRegisters::d2;
+#elif CPU(ARM_TRADITIONAL)
+        static const RegisterID returnValueRegister = ARMRegisters::r0;
+        static const RegisterID cachedResultRegister = ARMRegisters::r0;
+        static const RegisterID firstArgumentRegister = ARMRegisters::r0;
+
+        static const RegisterID timeoutCheckRegister = ARMRegisters::r5;
+        static const RegisterID callFrameRegister = ARMRegisters::r4;
+
+        static const RegisterID regT0 = ARMRegisters::r0;
+        static const RegisterID regT1 = ARMRegisters::r1;
+        static const RegisterID regT2 = ARMRegisters::r2;
+        // Callee preserved
+        static const RegisterID regT3 = ARMRegisters::r7;
+
+        static const RegisterID regS0 = ARMRegisters::S0;
+        // Callee preserved
+        static const RegisterID regS1 = ARMRegisters::S1;
+
+        static const RegisterID regStackPtr = ARMRegisters::sp;
+        static const RegisterID regLink = ARMRegisters::lr;
+
+        static const FPRegisterID fpRegT0 = ARMRegisters::d0;
+        static const FPRegisterID fpRegT1 = ARMRegisters::d1;
+        static const FPRegisterID fpRegT2 = ARMRegisters::d2;
 #else
     #error "JIT not supported on this platform."
 #endif
 #else
     #error "JIT not supported on this platform."
 #endif
@@ -252,10 +278,9 @@ namespace JSC {
         static const int patchGetByIdDefaultOffset = 256;
 
     public:
         static const int patchGetByIdDefaultOffset = 256;
 
     public:
-        static void compile(JSGlobalData* globalData, CodeBlock* codeBlock)
+        static JITCode compile(JSGlobalData* globalData, CodeBlock* codeBlock)
         {
         {
-            JIT jit(globalData, codeBlock);
-            jit.privateCompile();
+            return JIT(globalData, codeBlock).privateCompile();
         }
 
         static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress)
         }
 
         static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress)
@@ -292,15 +317,15 @@ namespace JSC {
             jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress);
         }
 
             jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress);
         }
 
-        static void compileCTIMachineTrampolines(JSGlobalData* globalData, RefPtr<ExecutablePool>* executablePool, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallPreLink, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
+        static void compileCTIMachineTrampolines(JSGlobalData* globalData, RefPtr<ExecutablePool>* executablePool, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
         {
             JIT jit(globalData);
         {
             JIT jit(globalData);
-            jit.privateCompileCTIMachineTrampolines(executablePool, globalData, ctiStringLengthTrampoline, ctiVirtualCallPreLink, ctiVirtualCallLink, ctiVirtualCall, ctiNativeCallThunk);
+            jit.privateCompileCTIMachineTrampolines(executablePool, globalData, ctiStringLengthTrampoline, ctiVirtualCallLink, ctiVirtualCall, ctiNativeCallThunk);
         }
 
         static void patchGetByIdSelf(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
         static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
         }
 
         static void patchGetByIdSelf(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
         static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
-        static void patchMethodCallProto(CodeBlock* codeblock, MethodCallLinkInfo&, JSFunction*, Structure*, JSObject*);
+        static void patchMethodCallProto(CodeBlock* codeblock, MethodCallLinkInfo&, JSFunction*, Structure*, JSObject*, ReturnAddressPtr);
 
         static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress)
         {
 
         static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress)
         {
@@ -328,7 +353,7 @@ namespace JSC {
         void privateCompileMainPass();
         void privateCompileLinkPass();
         void privateCompileSlowCases();
         void privateCompileMainPass();
         void privateCompileLinkPass();
         void privateCompileSlowCases();
-        void privateCompile();
+        JITCode privateCompile();
         void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
         void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, size_t cachedOffset);
         void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame);
         void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
         void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, size_t cachedOffset);
         void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame);
@@ -336,7 +361,7 @@ namespace JSC {
         void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
         void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress);
 
         void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
         void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress);
 
-        void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallPreLink, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk);
+        void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk);
         void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress);
 
         void addSlowCase(Jump);
         void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress);
 
         void addSlowCase(Jump);
@@ -355,14 +380,20 @@ namespace JSC {
 
         enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
         void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type);
 
         enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
         void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type);
+        bool isOperandConstantImmediateDouble(unsigned src);
+        
+        void emitLoadDouble(unsigned index, FPRegisterID value);
+        void emitLoadInt32ToDouble(unsigned index, FPRegisterID value);
+
+        Address addressFor(unsigned index, RegisterID base = callFrameRegister);
+
+        void testPrototype(Structure*, JumpList& failureCases);
 
 #if USE(JSVALUE32_64)
         Address tagFor(unsigned index, RegisterID base = callFrameRegister);
         Address payloadFor(unsigned index, RegisterID base = callFrameRegister);
 
 #if USE(JSVALUE32_64)
         Address tagFor(unsigned index, RegisterID base = callFrameRegister);
         Address payloadFor(unsigned index, RegisterID base = callFrameRegister);
-        Address addressFor(unsigned index, RegisterID base = callFrameRegister);
 
         bool getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant);
 
         bool getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant);
-        bool isOperandConstantImmediateDouble(unsigned src);
 
         void emitLoadTag(unsigned index, RegisterID tag);
         void emitLoadPayload(unsigned index, RegisterID payload);
 
         void emitLoadTag(unsigned index, RegisterID tag);
         void emitLoadPayload(unsigned index, RegisterID payload);
@@ -370,8 +401,6 @@ namespace JSC {
         void emitLoad(const JSValue& v, RegisterID tag, RegisterID payload);
         void emitLoad(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
         void emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1, unsigned index2, RegisterID tag2, RegisterID payload2);
         void emitLoad(const JSValue& v, RegisterID tag, RegisterID payload);
         void emitLoad(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
         void emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1, unsigned index2, RegisterID tag2, RegisterID payload2);
-        void emitLoadDouble(unsigned index, FPRegisterID value);
-        void emitLoadInt32ToDouble(unsigned index, FPRegisterID value);
 
         void emitStore(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
         void emitStore(unsigned index, const JSValue constant, RegisterID base = callFrameRegister);
 
         void emitStore(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
         void emitStore(unsigned index, const JSValue constant, RegisterID base = callFrameRegister);
@@ -399,6 +428,7 @@ namespace JSC {
 #endif
         void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset);
         void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
 #endif
         void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset);
         void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
+        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID structure, RegisterID offset);
         void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset);
 
         // Arithmetic opcode helpers
         void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset);
 
         // Arithmetic opcode helpers
@@ -406,7 +436,7 @@ namespace JSC {
         void emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
         void emitBinaryDoubleOp(OpcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true);
 
         void emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
         void emitBinaryDoubleOp(OpcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true);
 
-#if PLATFORM(X86)
+#if CPU(X86)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 7;
         static const int patchOffsetPutByIdExternalLoad = 13;
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 7;
         static const int patchOffsetPutByIdExternalLoad = 13;
@@ -435,6 +465,47 @@ namespace JSC {
         static const int patchOffsetMethodCheckProtoObj = 11;
         static const int patchOffsetMethodCheckProtoStruct = 18;
         static const int patchOffsetMethodCheckPutFunction = 29;
         static const int patchOffsetMethodCheckProtoObj = 11;
         static const int patchOffsetMethodCheckProtoStruct = 18;
         static const int patchOffsetMethodCheckPutFunction = 29;
+#elif CPU(ARM_TRADITIONAL)
+        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
+        static const int patchOffsetPutByIdStructure = 4;
+        static const int patchOffsetPutByIdExternalLoad = 16;
+        static const int patchLengthPutByIdExternalLoad = 4;
+        static const int patchOffsetPutByIdPropertyMapOffset1 = 20;
+        static const int patchOffsetPutByIdPropertyMapOffset2 = 28;
+        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
+        static const int patchOffsetGetByIdStructure = 4;
+        static const int patchOffsetGetByIdBranchToSlowCase = 16;
+        static const int patchOffsetGetByIdExternalLoad = 16;
+        static const int patchLengthGetByIdExternalLoad = 4;
+        static const int patchOffsetGetByIdPropertyMapOffset1 = 20;
+        static const int patchOffsetGetByIdPropertyMapOffset2 = 28;
+        static const int patchOffsetGetByIdPutResult = 36;
+#if ENABLE(OPCODE_SAMPLING)
+        #error "OPCODE_SAMPLING is not yet supported"
+#else
+        static const int patchOffsetGetByIdSlowCaseCall = 32;
+#endif
+        static const int patchOffsetOpCallCompareToJump = 12;
+
+        static const int patchOffsetMethodCheckProtoObj = 12;
+        static const int patchOffsetMethodCheckProtoStruct = 20;
+        static const int patchOffsetMethodCheckPutFunction = 32;
+
+        // sequenceOpCall
+        static const int sequenceOpCallInstructionSpace = 12;
+        static const int sequenceOpCallConstantSpace = 2;
+        // sequenceMethodCheck
+        static const int sequenceMethodCheckInstructionSpace = 40;
+        static const int sequenceMethodCheckConstantSpace = 6;
+        // sequenceGetByIdHotPath
+        static const int sequenceGetByIdHotPathInstructionSpace = 36;
+        static const int sequenceGetByIdHotPathConstantSpace = 4;
+        // sequenceGetByIdSlowCase
+        static const int sequenceGetByIdSlowCaseInstructionSpace = 40;
+        static const int sequenceGetByIdSlowCaseConstantSpace = 2;
+        // sequencePutById
+        static const int sequencePutByIdInstructionSpace = 36;
+        static const int sequencePutByIdConstantSpace = 4;
 #else
 #error "JSVALUE32_64 not supported on this platform."
 #endif
 #else
 #error "JSVALUE32_64 not supported on this platform."
 #endif
@@ -475,6 +546,7 @@ namespace JSC {
         JIT::Jump emitJumpIfNotImmediateInteger(RegisterID);
         JIT::Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
         void emitJumpSlowCaseIfNotImmediateInteger(RegisterID);
         JIT::Jump emitJumpIfNotImmediateInteger(RegisterID);
         JIT::Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
         void emitJumpSlowCaseIfNotImmediateInteger(RegisterID);
+        void emitJumpSlowCaseIfNotImmediateNumber(RegisterID);
         void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
 
 #if !USE(JSVALUE64)
         void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
 
 #if !USE(JSVALUE64)
@@ -487,7 +559,11 @@ namespace JSC {
 
         void emitTagAsBoolImmediate(RegisterID reg);
         void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
 
         void emitTagAsBoolImmediate(RegisterID reg);
         void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
-        void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
+#if USE(JSVALUE64)
+        void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase);
+#else
+        void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes);
+#endif
 
 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
         void compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned propertyAccessInstructionIndex);
 
 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
         void compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned propertyAccessInstructionIndex);
@@ -495,9 +571,10 @@ namespace JSC {
 #endif
         void compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset);
         void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset);
 #endif
         void compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset);
         void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset);
+        void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch);
         void compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset);
 
         void compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset);
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 10;
         static const int patchOffsetPutByIdExternalLoad = 20;
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 10;
         static const int patchOffsetPutByIdExternalLoad = 20;
@@ -511,16 +588,16 @@ namespace JSC {
         static const int patchOffsetGetByIdPropertyMapOffset = 31;
         static const int patchOffsetGetByIdPutResult = 31;
 #if ENABLE(OPCODE_SAMPLING)
         static const int patchOffsetGetByIdPropertyMapOffset = 31;
         static const int patchOffsetGetByIdPutResult = 31;
 #if ENABLE(OPCODE_SAMPLING)
-        static const int patchOffsetGetByIdSlowCaseCall = 66;
+        static const int patchOffsetGetByIdSlowCaseCall = 64;
 #else
 #else
-        static const int patchOffsetGetByIdSlowCaseCall = 44;
+        static const int patchOffsetGetByIdSlowCaseCall = 41;
 #endif
         static const int patchOffsetOpCallCompareToJump = 9;
 
         static const int patchOffsetMethodCheckProtoObj = 20;
         static const int patchOffsetMethodCheckProtoStruct = 30;
         static const int patchOffsetMethodCheckPutFunction = 50;
 #endif
         static const int patchOffsetOpCallCompareToJump = 9;
 
         static const int patchOffsetMethodCheckProtoObj = 20;
         static const int patchOffsetMethodCheckProtoStruct = 30;
         static const int patchOffsetMethodCheckPutFunction = 50;
-#elif PLATFORM(X86)
+#elif CPU(X86)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 7;
         static const int patchOffsetPutByIdExternalLoad = 13;
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 7;
         static const int patchOffsetPutByIdExternalLoad = 13;
@@ -547,32 +624,83 @@ namespace JSC {
         static const int patchOffsetMethodCheckProtoObj = 11;
         static const int patchOffsetMethodCheckProtoStruct = 18;
         static const int patchOffsetMethodCheckPutFunction = 29;
         static const int patchOffsetMethodCheckProtoObj = 11;
         static const int patchOffsetMethodCheckProtoStruct = 18;
         static const int patchOffsetMethodCheckPutFunction = 29;
-#elif PLATFORM_ARM_ARCH(7)
+#elif CPU(ARM_THUMB2)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 10;
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 10;
-        static const int patchOffsetPutByIdExternalLoad = 20;
+        static const int patchOffsetPutByIdExternalLoad = 26;
         static const int patchLengthPutByIdExternalLoad = 12;
         static const int patchLengthPutByIdExternalLoad = 12;
-        static const int patchOffsetPutByIdPropertyMapOffset = 40;
+        static const int patchOffsetPutByIdPropertyMapOffset = 46;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 10;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 10;
-        static const int patchOffsetGetByIdBranchToSlowCase = 20;
-        static const int patchOffsetGetByIdExternalLoad = 20;
+        static const int patchOffsetGetByIdBranchToSlowCase = 26;
+        static const int patchOffsetGetByIdExternalLoad = 26;
         static const int patchLengthGetByIdExternalLoad = 12;
         static const int patchLengthGetByIdExternalLoad = 12;
-        static const int patchOffsetGetByIdPropertyMapOffset = 40;
-        static const int patchOffsetGetByIdPutResult = 44;
+        static const int patchOffsetGetByIdPropertyMapOffset = 46;
+        static const int patchOffsetGetByIdPutResult = 50;
 #if ENABLE(OPCODE_SAMPLING)
         static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE
 #else
         static const int patchOffsetGetByIdSlowCaseCall = 28;
 #endif
 #if ENABLE(OPCODE_SAMPLING)
         static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE
 #else
         static const int patchOffsetGetByIdSlowCaseCall = 28;
 #endif
-        static const int patchOffsetOpCallCompareToJump = 10;
+        static const int patchOffsetOpCallCompareToJump = 16;
 
 
-        static const int patchOffsetMethodCheckProtoObj = 18;
-        static const int patchOffsetMethodCheckProtoStruct = 28;
-        static const int patchOffsetMethodCheckPutFunction = 46;
+        static const int patchOffsetMethodCheckProtoObj = 24;
+        static const int patchOffsetMethodCheckProtoStruct = 34;
+        static const int patchOffsetMethodCheckPutFunction = 58;
+#elif CPU(ARM_TRADITIONAL)
+        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
+        static const int patchOffsetPutByIdStructure = 4;
+        static const int patchOffsetPutByIdExternalLoad = 16;
+        static const int patchLengthPutByIdExternalLoad = 4;
+        static const int patchOffsetPutByIdPropertyMapOffset = 20;
+        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
+        static const int patchOffsetGetByIdStructure = 4;
+        static const int patchOffsetGetByIdBranchToSlowCase = 16;
+        static const int patchOffsetGetByIdExternalLoad = 16;
+        static const int patchLengthGetByIdExternalLoad = 4;
+        static const int patchOffsetGetByIdPropertyMapOffset = 20;
+        static const int patchOffsetGetByIdPutResult = 28;
+#if ENABLE(OPCODE_SAMPLING)
+        #error "OPCODE_SAMPLING is not yet supported"
+#else
+        static const int patchOffsetGetByIdSlowCaseCall = 28;
+#endif
+        static const int patchOffsetOpCallCompareToJump = 12;
+
+        static const int patchOffsetMethodCheckProtoObj = 12;
+        static const int patchOffsetMethodCheckProtoStruct = 20;
+        static const int patchOffsetMethodCheckPutFunction = 32;
+
+        // sequenceOpCall
+        static const int sequenceOpCallInstructionSpace = 12;
+        static const int sequenceOpCallConstantSpace = 2;
+        // sequenceMethodCheck
+        static const int sequenceMethodCheckInstructionSpace = 40;
+        static const int sequenceMethodCheckConstantSpace = 6;
+        // sequenceGetByIdHotPath
+        static const int sequenceGetByIdHotPathInstructionSpace = 28;
+        static const int sequenceGetByIdHotPathConstantSpace = 3;
+        // sequenceGetByIdSlowCase
+        static const int sequenceGetByIdSlowCaseInstructionSpace = 32;
+        static const int sequenceGetByIdSlowCaseConstantSpace = 2;
+        // sequencePutById
+        static const int sequencePutByIdInstructionSpace = 28;
+        static const int sequencePutByIdConstantSpace = 3;
 #endif
 #endif // USE(JSVALUE32_64)
 
 #endif
 #endif // USE(JSVALUE32_64)
 
+#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
+#define BEGIN_UNINTERRUPTED_SEQUENCE(name) beginUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace)
+#define END_UNINTERRUPTED_SEQUENCE(name) endUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace)
+
+        void beginUninterruptedSequence(int, int);
+        void endUninterruptedSequence(int, int);
+
+#else
+#define BEGIN_UNINTERRUPTED_SEQUENCE(name)
+#define END_UNINTERRUPTED_SEQUENCE(name)
+#endif
+
         void emit_op_add(Instruction*);
         void emit_op_bitand(Instruction*);
         void emit_op_bitnot(Instruction*);
         void emit_op_add(Instruction*);
         void emit_op_bitand(Instruction*);
         void emit_op_bitnot(Instruction*);
@@ -596,6 +724,7 @@ namespace JSC {
         void emit_op_eq_null(Instruction*);
         void emit_op_get_by_id(Instruction*);
         void emit_op_get_by_val(Instruction*);
         void emit_op_eq_null(Instruction*);
         void emit_op_get_by_id(Instruction*);
         void emit_op_get_by_val(Instruction*);
+        void emit_op_get_by_pname(Instruction*);
         void emit_op_get_global_var(Instruction*);
         void emit_op_get_scoped_var(Instruction*);
         void emit_op_init_arguments(Instruction*);
         void emit_op_get_global_var(Instruction*);
         void emit_op_get_scoped_var(Instruction*);
         void emit_op_init_arguments(Instruction*);
@@ -607,6 +736,7 @@ namespace JSC {
         void emit_op_jneq_null(Instruction*);
         void emit_op_jneq_ptr(Instruction*);
         void emit_op_jnless(Instruction*);
         void emit_op_jneq_null(Instruction*);
         void emit_op_jneq_ptr(Instruction*);
         void emit_op_jnless(Instruction*);
+        void emit_op_jless(Instruction*);
         void emit_op_jnlesseq(Instruction*);
         void emit_op_jsr(Instruction*);
         void emit_op_jtrue(Instruction*);
         void emit_op_jnlesseq(Instruction*);
         void emit_op_jsr(Instruction*);
         void emit_op_jtrue(Instruction*);
@@ -615,6 +745,7 @@ namespace JSC {
         void emit_op_loop_if_less(Instruction*);
         void emit_op_loop_if_lesseq(Instruction*);
         void emit_op_loop_if_true(Instruction*);
         void emit_op_loop_if_less(Instruction*);
         void emit_op_loop_if_lesseq(Instruction*);
         void emit_op_loop_if_true(Instruction*);
+        void emit_op_loop_if_false(Instruction*);
         void emit_op_lshift(Instruction*);
         void emit_op_method_check(Instruction*);
         void emit_op_mod(Instruction*);
         void emit_op_lshift(Instruction*);
         void emit_op_method_check(Instruction*);
         void emit_op_mod(Instruction*);
@@ -629,6 +760,7 @@ namespace JSC {
         void emit_op_new_func_exp(Instruction*);
         void emit_op_new_object(Instruction*);
         void emit_op_new_regexp(Instruction*);
         void emit_op_new_func_exp(Instruction*);
         void emit_op_new_object(Instruction*);
         void emit_op_new_regexp(Instruction*);
+        void emit_op_get_pnames(Instruction*);
         void emit_op_next_pname(Instruction*);
         void emit_op_not(Instruction*);
         void emit_op_nstricteq(Instruction*);
         void emit_op_next_pname(Instruction*);
         void emit_op_not(Instruction*);
         void emit_op_nstricteq(Instruction*);
@@ -684,14 +816,17 @@ namespace JSC {
         void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_get_by_pname(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_less(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_lesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_true(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_less(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_lesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_true(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_loop_if_false(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&);
@@ -716,6 +851,7 @@ namespace JSC {
         /* These functions are deprecated: Please use JITStubCall instead. */
         void emitPutJITStubArg(RegisterID src, unsigned argumentNumber);
 #if USE(JSVALUE32_64)
         /* These functions are deprecated: Please use JITStubCall instead. */
         void emitPutJITStubArg(RegisterID src, unsigned argumentNumber);
 #if USE(JSVALUE32_64)
+        void emitPutJITStubArg(RegisterID tag, RegisterID payload, unsigned argumentNumber);
         void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2);
 #else
         void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch);
         void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2);
 #else
         void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch);
@@ -809,8 +945,55 @@ namespace JSC {
 #else
         int m_lastResultBytecodeRegister;
         unsigned m_jumpTargetsPosition;
 #else
         int m_lastResultBytecodeRegister;
         unsigned m_jumpTargetsPosition;
+#endif
+
+#ifndef NDEBUG
+#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
+        Label m_uninterruptedInstructionSequenceBegin;
+        int m_uninterruptedConstantSequenceBegin;
+#endif
 #endif
     } JIT_CLASS_ALIGNMENT;
 #endif
     } JIT_CLASS_ALIGNMENT;
+
+    inline void JIT::emit_op_loop(Instruction* currentInstruction)
+    {
+        emitTimeoutCheck();
+        emit_op_jmp(currentInstruction);
+    }
+
+    inline void JIT::emit_op_loop_if_true(Instruction* currentInstruction)
+    {
+        emitTimeoutCheck();
+        emit_op_jtrue(currentInstruction);
+    }
+
+    inline void JIT::emitSlow_op_loop_if_true(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+    {
+        emitSlow_op_jtrue(currentInstruction, iter);
+    }
+
+    inline void JIT::emit_op_loop_if_false(Instruction* currentInstruction)
+    {
+        emitTimeoutCheck();
+        emit_op_jfalse(currentInstruction);
+    }
+
+    inline void JIT::emitSlow_op_loop_if_false(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+    {
+        emitSlow_op_jfalse(currentInstruction, iter);
+    }
+
+    inline void JIT::emit_op_loop_if_less(Instruction* currentInstruction)
+    {
+        emitTimeoutCheck();
+        emit_op_jless(currentInstruction);
+    }
+
+    inline void JIT::emitSlow_op_loop_if_less(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+    {
+        emitSlow_op_jless(currentInstruction, iter);
+    }
+
 } // namespace JSC
 
 #endif // ENABLE(JIT)
 } // namespace JSC
 
 #endif // ENABLE(JIT)
index 3bd7146109242f59e98f9fca583f52db7117a520..feee8d21b8aed47700f1187c9ed14f6a322742aa 100644 (file)
@@ -98,16 +98,16 @@ void JIT::emit_op_jnless(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT3, regT2);
         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT3, regT2);
         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
-        addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target + 3);
+        addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
     } else if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
     } else if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3);
+        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
     } else {
         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
     } else {
         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
-        addJump(branch32(GreaterThanOrEqual, regT0, regT2), target + 3);
+        addJump(branch32(GreaterThanOrEqual, regT0, regT2), target);
     }
 
     if (!supportsFloatingPoint()) {
     }
 
     if (!supportsFloatingPoint()) {
@@ -145,7 +145,70 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     stubCall.call();
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     stubCall.call();
-    emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+    emitJumpSlowToHot(branchTest32(Zero, regT0), target);
+}
+
+void JIT::emit_op_jless(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    JumpList notInt32Op1;
+    JumpList notInt32Op2;
+
+    // Int32 less.
+    if (isOperandConstantImmediateInt(op1)) {
+        emitLoad(op2, regT3, regT2);
+        notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
+    } else if (isOperandConstantImmediateInt(op2)) {
+        emitLoad(op1, regT1, regT0);
+        notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
+    } else {
+        emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+        notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        addJump(branch32(LessThan, regT0, regT2), target);
+    }
+
+    if (!supportsFloatingPoint()) {
+        addSlowCase(notInt32Op1);
+        addSlowCase(notInt32Op2);
+        return;
+    }
+    Jump end = jump();
+
+    // Double less.
+    emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
+    end.link(this);
+}
+
+void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    if (!supportsFloatingPoint()) {
+        if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+            linkSlowCase(iter); // int32 check
+        linkSlowCase(iter); // int32 check
+    } else {
+        if (!isOperandConstantImmediateInt(op1)) {
+            linkSlowCase(iter); // double check
+            linkSlowCase(iter); // int32 check
+        }
+        if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
+            linkSlowCase(iter); // double check
+    }
+
+    JITStubCall stubCall(this, cti_op_jless);
+    stubCall.addArgument(op1);
+    stubCall.addArgument(op2);
+    stubCall.call();
+    emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
 }
 
 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
@@ -161,16 +224,16 @@ void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT3, regT2);
         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT3, regT2);
         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
-        addJump(branch32(LessThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target + 3);
+        addJump(branch32(LessThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
     } else if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
     } else if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-        addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3);
+        addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
     } else {
         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
     } else {
         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
-        addJump(branch32(GreaterThan, regT0, regT2), target + 3);
+        addJump(branch32(GreaterThan, regT0, regT2), target);
     }
 
     if (!supportsFloatingPoint()) {
     }
 
     if (!supportsFloatingPoint()) {
@@ -208,7 +271,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     stubCall.call();
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     stubCall.call();
-    emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+    emitJumpSlowToHot(branchTest32(Zero, regT0), target);
 }
 
 // LeftShift (<<)
 }
 
 // LeftShift (<<)
@@ -566,6 +629,14 @@ void JIT::emit_op_add(Instruction* currentInstruction)
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
+    if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
+        JITStubCall stubCall(this, cti_op_add);
+        stubCall.addArgument(op1);
+        stubCall.addArgument(op2);
+        stubCall.call(dst);
+        return;
+    }
+
     JumpList notInt32Op1;
     JumpList notInt32Op2;
 
     JumpList notInt32Op1;
     JumpList notInt32Op2;
 
@@ -630,6 +701,9 @@ void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
+    if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
+        return;
+
     unsigned op;
     int32_t constant;
     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
     unsigned op;
     int32_t constant;
     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
@@ -818,11 +892,15 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi
                 break;
             case op_jnless:
                 emitLoadDouble(op1, fpRegT2);
                 break;
             case op_jnless:
                 emitLoadDouble(op1, fpRegT2);
-                addJump(branchDouble(DoubleLessThanOrEqual, fpRegT0, fpRegT2), dst + 3);
+                addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst);
+                break;
+            case op_jless:
+                emitLoadDouble(op1, fpRegT2);
+                addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst);
                 break;
             case op_jnlesseq:
                 emitLoadDouble(op1, fpRegT2);
                 break;
             case op_jnlesseq:
                 emitLoadDouble(op1, fpRegT2);
-                addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT2), dst + 3);
+                addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst);
                 break;
             default:
                 ASSERT_NOT_REACHED();
                 break;
             default:
                 ASSERT_NOT_REACHED();
@@ -871,11 +949,15 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi
                 break;
             case op_jnless:
                 emitLoadDouble(op2, fpRegT1);
                 break;
             case op_jnless:
                 emitLoadDouble(op2, fpRegT1);
-                addJump(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), dst + 3);
+                addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst);
+                break;
+            case op_jless:
+                emitLoadDouble(op2, fpRegT1);
+                addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst);
                 break;
             case op_jnlesseq:
                 emitLoadDouble(op2, fpRegT1);
                 break;
             case op_jnlesseq:
                 emitLoadDouble(op2, fpRegT1);
-                addJump(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), dst + 3);
+                addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst);
                 break;
             default:
                 ASSERT_NOT_REACHED();
                 break;
             default:
                 ASSERT_NOT_REACHED();
@@ -989,20 +1071,11 @@ void JIT::emit_op_div(Instruction* currentInstruction)
     divDouble(fpRegT1, fpRegT0);
 
     JumpList doubleResult;
     divDouble(fpRegT1, fpRegT0);
 
     JumpList doubleResult;
-    if (!isOperandConstantImmediateInt(op1) || getConstantOperand(op1).asInt32() > 1) {
-        m_assembler.cvttsd2si_rr(fpRegT0, regT0);
-        convertInt32ToDouble(regT0, fpRegT1);
-        m_assembler.ucomisd_rr(fpRegT1, fpRegT0);
-
-        doubleResult.append(m_assembler.jne());
-        doubleResult.append(m_assembler.jp());
-        
-        doubleResult.append(branchTest32(Zero, regT0));
+    branchConvertDoubleToInt32(fpRegT0, regT0, doubleResult, fpRegT1);
 
 
-        // Int32 result.
-        emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
-        end.append(jump());
-    }
+    // Int32 result.
+    emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+    end.append(jump());
 
     // Double result.
     doubleResult.link(this);
 
     // Double result.
     doubleResult.link(this);
@@ -1043,7 +1116,7 @@ void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
-#if PLATFORM(X86) || PLATFORM(X86_64)
+#if CPU(X86) || CPU(X86_64)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
@@ -1052,33 +1125,33 @@ void JIT::emit_op_mod(Instruction* currentInstruction)
     unsigned op2 = currentInstruction[3].u.operand;
 
     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
     unsigned op2 = currentInstruction[3].u.operand;
 
     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
-        emitLoad(op1, X86::edx, X86::eax);
-        move(Imm32(getConstantOperand(op2).asInt32()), X86::ecx);
-        addSlowCase(branch32(NotEqual, X86::edx, Imm32(JSValue::Int32Tag)));
+        emitLoad(op1, X86Registers::edx, X86Registers::eax);
+        move(Imm32(getConstantOperand(op2).asInt32()), X86Registers::ecx);
+        addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag)));
         if (getConstantOperand(op2).asInt32() == -1)
         if (getConstantOperand(op2).asInt32() == -1)
-            addSlowCase(branch32(Equal, X86::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
+            addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
     } else {
     } else {
-        emitLoad2(op1, X86::edx, X86::eax, op2, X86::ebx, X86::ecx);
-        addSlowCase(branch32(NotEqual, X86::edx, Imm32(JSValue::Int32Tag)));
-        addSlowCase(branch32(NotEqual, X86::ebx, Imm32(JSValue::Int32Tag)));
+        emitLoad2(op1, X86Registers::edx, X86Registers::eax, op2, X86Registers::ebx, X86Registers::ecx);
+        addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, X86Registers::ebx, Imm32(JSValue::Int32Tag)));
 
 
-        addSlowCase(branch32(Equal, X86::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
-        addSlowCase(branch32(Equal, X86::ecx, Imm32(0))); // divide by 0
+        addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
+        addSlowCase(branch32(Equal, X86Registers::ecx, Imm32(0))); // divide by 0
     }
 
     }
 
-    move(X86::eax, X86::ebx); // Save dividend payload, in case of 0.
+    move(X86Registers::eax, X86Registers::ebx); // Save dividend payload, in case of 0.
     m_assembler.cdq();
     m_assembler.cdq();
-    m_assembler.idivl_r(X86::ecx);
+    m_assembler.idivl_r(X86Registers::ecx);
     
     // If the remainder is zero and the dividend is negative, the result is -0.
     
     // If the remainder is zero and the dividend is negative, the result is -0.
-    Jump storeResult1 = branchTest32(NonZero, X86::edx);
-    Jump storeResult2 = branchTest32(Zero, X86::ebx, Imm32(0x80000000)); // not negative
+    Jump storeResult1 = branchTest32(NonZero, X86Registers::edx);
+    Jump storeResult2 = branchTest32(Zero, X86Registers::ebx, Imm32(0x80000000)); // not negative
     emitStore(dst, jsNumber(m_globalData, -0.0));
     Jump end = jump();
 
     storeResult1.link(this);
     storeResult2.link(this);
     emitStore(dst, jsNumber(m_globalData, -0.0));
     Jump end = jump();
 
     storeResult1.link(this);
     storeResult2.link(this);
-    emitStoreInt32(dst, X86::edx, (op1 == dst || op2 == dst));
+    emitStoreInt32(dst, X86Registers::edx, (op1 == dst || op2 == dst));
     end.link(this);
 }
 
     end.link(this);
 }
 
@@ -1105,7 +1178,7 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>
     stubCall.call(dst);
 }
 
     stubCall.call(dst);
 }
 
-#else // PLATFORM(X86) || PLATFORM(X86_64)
+#else // CPU(X86) || CPU(X86_64)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
@@ -1123,7 +1196,7 @@ void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&)
 {
 }
 
 {
 }
 
-#endif // PLATFORM(X86) || PLATFORM(X86_64)
+#endif // CPU(X86) || CPU(X86_64)
 
 /* ------------------------------ END: OP_MOD ------------------------------ */
 
 
 /* ------------------------------ END: OP_MOD ------------------------------ */
 
@@ -1141,13 +1214,8 @@ void JIT::emit_op_lshift(Instruction* currentInstruction)
     emitJumpSlowCaseIfNotImmediateInteger(regT2);
     emitFastArithImmToInt(regT0);
     emitFastArithImmToInt(regT2);
     emitJumpSlowCaseIfNotImmediateInteger(regT2);
     emitFastArithImmToInt(regT0);
     emitFastArithImmToInt(regT2);
-#if !PLATFORM(X86)
-    // Mask with 0x1f as per ecma-262 11.7.2 step 7.
-    // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction.
-    and32(Imm32(0x1f), regT2);
-#endif
     lshift32(regT2, regT0);
     lshift32(regT2, regT0);
-#if !USE(JSVALUE64)
+#if USE(JSVALUE32)
     addSlowCase(branchAdd32(Overflow, regT0, regT0));
     signExtend32ToPtr(regT0, regT0);
 #endif
     addSlowCase(branchAdd32(Overflow, regT0, regT0));
     signExtend32ToPtr(regT0, regT0);
 #endif
@@ -1192,11 +1260,7 @@ void JIT::emit_op_rshift(Instruction* currentInstruction)
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         // Mask with 0x1f as per ecma-262 11.7.2 step 7.
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         // Mask with 0x1f as per ecma-262 11.7.2 step 7.
-#if USE(JSVALUE64)
         rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
         rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
-#else
-        rshiftPtr(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
-#endif
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT2);
         if (supportsFloatingPointTruncate()) {
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT2);
         if (supportsFloatingPointTruncate()) {
@@ -1223,15 +1287,9 @@ void JIT::emit_op_rshift(Instruction* currentInstruction)
             emitJumpSlowCaseIfNotImmediateInteger(regT2);
         }
         emitFastArithImmToInt(regT2);
             emitJumpSlowCaseIfNotImmediateInteger(regT2);
         }
         emitFastArithImmToInt(regT2);
-#if !PLATFORM(X86)
-        // Mask with 0x1f as per ecma-262 11.7.2 step 7.
-        // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction.
-        and32(Imm32(0x1f), regT2);
-#endif
-#if USE(JSVALUE64)
         rshift32(regT2, regT0);
         rshift32(regT2, regT0);
-#else
-        rshiftPtr(regT2, regT0);
+#if USE(JSVALUE32)
+        signExtend32ToPtr(regT0, regT0);
 #endif
     }
 #if USE(JSVALUE64)
 #endif
     }
 #if USE(JSVALUE64)
@@ -1302,7 +1360,7 @@ void JIT::emit_op_jnless(Instruction* currentInstruction)
 #else
         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
 #endif
 #else
         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
 #endif
-        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target + 3);
+        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
@@ -1311,13 +1369,13 @@ void JIT::emit_op_jnless(Instruction* currentInstruction)
 #else
         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
 #endif
 #else
         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
 #endif
-        addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target + 3);
+        addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target);
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
 
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
 
-        addJump(branch32(GreaterThanOrEqual, regT0, regT1), target + 3);
+        addJump(branch32(GreaterThanOrEqual, regT0, regT1), target);
     }
 }
 
     }
 }
 
@@ -1354,7 +1412,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
             move(Imm32(op2imm), regT1);
             convertInt32ToDouble(regT1, fpRegT1);
 
             move(Imm32(op2imm), regT1);
             convertInt32ToDouble(regT1, fpRegT1);
 
-            emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), target + 3);
+            emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
@@ -1371,7 +1429,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
         stubCall.addArgument(regT0);
         stubCall.addArgument(op2, regT2);
         stubCall.call();
         stubCall.addArgument(regT0);
         stubCall.addArgument(op2, regT2);
         stubCall.call();
-        emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
 
     } else if (isOperandConstantImmediateInt(op1)) {
         linkSlowCase(iter);
 
     } else if (isOperandConstantImmediateInt(op1)) {
         linkSlowCase(iter);
@@ -1395,7 +1453,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
             move(Imm32(op1imm), regT0);
             convertInt32ToDouble(regT0, fpRegT0);
 
             move(Imm32(op1imm), regT0);
             convertInt32ToDouble(regT0, fpRegT0);
 
-            emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), target + 3);
+            emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
@@ -1412,7 +1470,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
         stubCall.addArgument(op1, regT2);
         stubCall.addArgument(regT1);
         stubCall.call();
         stubCall.addArgument(op1, regT2);
         stubCall.addArgument(regT1);
         stubCall.call();
-        emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
 
     } else {
         linkSlowCase(iter);
 
     } else {
         linkSlowCase(iter);
@@ -1441,7 +1499,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
 #endif
 
             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
 #endif
 
-            emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), target + 3);
+            emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
@@ -1464,7 +1522,192 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
         stubCall.addArgument(regT0);
         stubCall.addArgument(regT1);
         stubCall.call();
         stubCall.addArgument(regT0);
         stubCall.addArgument(regT1);
         stubCall.call();
-        emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
+    }
+}
+
+void JIT::emit_op_jless(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    // We generate inline code for the following cases in the fast path:
+    // - int immediate to constant int immediate
+    // - constant int immediate to int immediate
+    // - int immediate to int immediate
+
+    if (isOperandConstantImmediateInt(op2)) {
+        emitGetVirtualRegister(op1, regT0);
+        emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+        int32_t op2imm = getConstantOperandImmediateInt(op2);
+#else
+        int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+        addJump(branch32(LessThan, regT0, Imm32(op2imm)), target);
+    } else if (isOperandConstantImmediateInt(op1)) {
+        emitGetVirtualRegister(op2, regT1);
+        emitJumpSlowCaseIfNotImmediateInteger(regT1);
+#if USE(JSVALUE64)
+        int32_t op1imm = getConstantOperandImmediateInt(op1);
+#else
+        int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
+#endif
+        addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target);
+    } else {
+        emitGetVirtualRegisters(op1, regT0, op2, regT1);
+        emitJumpSlowCaseIfNotImmediateInteger(regT0);
+        emitJumpSlowCaseIfNotImmediateInteger(regT1);
+
+        addJump(branch32(LessThan, regT0, regT1), target);
+    }
+}
+
+void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    // We generate inline code for the following cases in the slow path:
+    // - floating-point number to constant int immediate
+    // - constant int immediate to floating-point number
+    // - floating-point number to floating-point number.
+
+    if (isOperandConstantImmediateInt(op2)) {
+        linkSlowCase(iter);
+
+        if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+            Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
+            addPtr(tagTypeNumberRegister, regT0);
+            movePtrToDouble(regT0, fpRegT0);
+#else
+            Jump fail1;
+            if (!m_codeBlock->isKnownNotImmediate(op1))
+                fail1 = emitJumpIfNotJSCell(regT0);
+
+            Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
+            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
+#endif
+            
+            int32_t op2imm = getConstantOperand(op2).asInt32();
+                    
+            move(Imm32(op2imm), regT1);
+            convertInt32ToDouble(regT1, fpRegT1);
+
+            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
+
+            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
+
+#if USE(JSVALUE64)
+            fail1.link(this);
+#else
+            if (!m_codeBlock->isKnownNotImmediate(op1))
+                fail1.link(this);
+            fail2.link(this);
+#endif
+        }
+
+        JITStubCall stubCall(this, cti_op_jless);
+        stubCall.addArgument(regT0);
+        stubCall.addArgument(op2, regT2);
+        stubCall.call();
+        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
+
+    } else if (isOperandConstantImmediateInt(op1)) {
+        linkSlowCase(iter);
+
+        if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+            Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
+            addPtr(tagTypeNumberRegister, regT1);
+            movePtrToDouble(regT1, fpRegT1);
+#else
+            Jump fail1;
+            if (!m_codeBlock->isKnownNotImmediate(op2))
+                fail1 = emitJumpIfNotJSCell(regT1);
+            
+            Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
+            loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
+#endif
+            
+            int32_t op1imm = getConstantOperand(op1).asInt32();
+                    
+            move(Imm32(op1imm), regT0);
+            convertInt32ToDouble(regT0, fpRegT0);
+
+            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
+
+            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
+
+#if USE(JSVALUE64)
+            fail1.link(this);
+#else
+            if (!m_codeBlock->isKnownNotImmediate(op2))
+                fail1.link(this);
+            fail2.link(this);
+#endif
+        }
+
+        JITStubCall stubCall(this, cti_op_jless);
+        stubCall.addArgument(op1, regT2);
+        stubCall.addArgument(regT1);
+        stubCall.call();
+        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
+
+    } else {
+        linkSlowCase(iter);
+
+        if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+            Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
+            Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
+            Jump fail3 = emitJumpIfImmediateInteger(regT1);
+            addPtr(tagTypeNumberRegister, regT0);
+            addPtr(tagTypeNumberRegister, regT1);
+            movePtrToDouble(regT0, fpRegT0);
+            movePtrToDouble(regT1, fpRegT1);
+#else
+            Jump fail1;
+            if (!m_codeBlock->isKnownNotImmediate(op1))
+                fail1 = emitJumpIfNotJSCell(regT0);
+
+            Jump fail2;
+            if (!m_codeBlock->isKnownNotImmediate(op2))
+                fail2 = emitJumpIfNotJSCell(regT1);
+
+            Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
+            Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
+            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
+            loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
+#endif
+
+            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
+
+            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
+
+#if USE(JSVALUE64)
+            fail1.link(this);
+            fail2.link(this);
+            fail3.link(this);
+#else
+            if (!m_codeBlock->isKnownNotImmediate(op1))
+                fail1.link(this);
+            if (!m_codeBlock->isKnownNotImmediate(op2))
+                fail2.link(this);
+            fail3.link(this);
+            fail4.link(this);
+#endif
+        }
+
+        linkSlowCase(iter);
+        JITStubCall stubCall(this, cti_op_jless);
+        stubCall.addArgument(regT0);
+        stubCall.addArgument(regT1);
+        stubCall.call();
+        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
     }
 }
 
     }
 }
 
@@ -1487,7 +1730,7 @@ void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
 #else
         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
 #endif
 #else
         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
 #endif
-        addJump(branch32(GreaterThan, regT0, Imm32(op2imm)), target + 3);
+        addJump(branch32(GreaterThan, regT0, Imm32(op2imm)), target);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
@@ -1496,13 +1739,13 @@ void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
 #else
         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
 #endif
 #else
         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
 #endif
-        addJump(branch32(LessThan, regT1, Imm32(op1imm)), target + 3);
+        addJump(branch32(LessThan, regT1, Imm32(op1imm)), target);
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
 
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
 
-        addJump(branch32(GreaterThan, regT0, regT1), target + 3);
+        addJump(branch32(GreaterThan, regT0, regT1), target);
     }
 }
 
     }
 }
 
@@ -1539,7 +1782,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE
             move(Imm32(op2imm), regT1);
             convertInt32ToDouble(regT1, fpRegT1);
 
             move(Imm32(op2imm), regT1);
             convertInt32ToDouble(regT1, fpRegT1);
 
-            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), target + 3);
+            emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
@@ -1556,7 +1799,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE
         stubCall.addArgument(regT0);
         stubCall.addArgument(op2, regT2);
         stubCall.call();
         stubCall.addArgument(regT0);
         stubCall.addArgument(op2, regT2);
         stubCall.call();
-        emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
 
     } else if (isOperandConstantImmediateInt(op1)) {
         linkSlowCase(iter);
 
     } else if (isOperandConstantImmediateInt(op1)) {
         linkSlowCase(iter);
@@ -1580,7 +1823,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE
             move(Imm32(op1imm), regT0);
             convertInt32ToDouble(regT0, fpRegT0);
 
             move(Imm32(op1imm), regT0);
             convertInt32ToDouble(regT0, fpRegT0);
 
-            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), target + 3);
+            emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
@@ -1597,7 +1840,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE
         stubCall.addArgument(op1, regT2);
         stubCall.addArgument(regT1);
         stubCall.call();
         stubCall.addArgument(op1, regT2);
         stubCall.addArgument(regT1);
         stubCall.call();
-        emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
 
     } else {
         linkSlowCase(iter);
 
     } else {
         linkSlowCase(iter);
@@ -1626,7 +1869,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE
             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
 #endif
 
             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
 #endif
 
-            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), target + 3);
+            emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
@@ -1649,7 +1892,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE
         stubCall.addArgument(regT0);
         stubCall.addArgument(regT1);
         stubCall.call();
         stubCall.addArgument(regT0);
         stubCall.addArgument(regT1);
         stubCall.call();
-        emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3);
+        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
     }
 }
 
     }
 }
 
@@ -1838,7 +2081,7 @@ void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEn
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
-#if PLATFORM(X86) || PLATFORM(X86_64)
+#if CPU(X86) || CPU(X86_64)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
@@ -1846,21 +2089,21 @@ void JIT::emit_op_mod(Instruction* currentInstruction)
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
 
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
 
-    emitGetVirtualRegisters(op1, X86::eax, op2, X86::ecx);
-    emitJumpSlowCaseIfNotImmediateInteger(X86::eax);
-    emitJumpSlowCaseIfNotImmediateInteger(X86::ecx);
+    emitGetVirtualRegisters(op1, X86Registers::eax, op2, X86Registers::ecx);
+    emitJumpSlowCaseIfNotImmediateInteger(X86Registers::eax);
+    emitJumpSlowCaseIfNotImmediateInteger(X86Registers::ecx);
 #if USE(JSVALUE64)
 #if USE(JSVALUE64)
-    addSlowCase(branchPtr(Equal, X86::ecx, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))));
+    addSlowCase(branchPtr(Equal, X86Registers::ecx, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))));
     m_assembler.cdq();
     m_assembler.cdq();
-    m_assembler.idivl_r(X86::ecx);
+    m_assembler.idivl_r(X86Registers::ecx);
 #else
 #else
-    emitFastArithDeTagImmediate(X86::eax);
-    addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86::ecx));
+    emitFastArithDeTagImmediate(X86Registers::eax);
+    addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86Registers::ecx));
     m_assembler.cdq();
     m_assembler.cdq();
-    m_assembler.idivl_r(X86::ecx);
-    signExtend32ToPtr(X86::edx, X86::edx);
+    m_assembler.idivl_r(X86Registers::ecx);
+    signExtend32ToPtr(X86Registers::edx, X86Registers::edx);
 #endif
 #endif
-    emitFastArithReTagImmediate(X86::edx, X86::eax);
+    emitFastArithReTagImmediate(X86Registers::edx, X86Registers::eax);
     emitPutVirtualRegister(result);
 }
 
     emitPutVirtualRegister(result);
 }
 
@@ -1876,18 +2119,18 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>
     Jump notImm1 = getSlowCase(iter);
     Jump notImm2 = getSlowCase(iter);
     linkSlowCase(iter);
     Jump notImm1 = getSlowCase(iter);
     Jump notImm2 = getSlowCase(iter);
     linkSlowCase(iter);
-    emitFastArithReTagImmediate(X86::eax, X86::eax);
-    emitFastArithReTagImmediate(X86::ecx, X86::ecx);
+    emitFastArithReTagImmediate(X86Registers::eax, X86Registers::eax);
+    emitFastArithReTagImmediate(X86Registers::ecx, X86Registers::ecx);
     notImm1.link(this);
     notImm2.link(this);
 #endif
     JITStubCall stubCall(this, cti_op_mod);
     notImm1.link(this);
     notImm2.link(this);
 #endif
     JITStubCall stubCall(this, cti_op_mod);
-    stubCall.addArgument(X86::eax);
-    stubCall.addArgument(X86::ecx);
+    stubCall.addArgument(X86Registers::eax);
+    stubCall.addArgument(X86Registers::ecx);
     stubCall.call(result);
 }
 
     stubCall.call(result);
 }
 
-#else // PLATFORM(X86) || PLATFORM(X86_64)
+#else // CPU(X86) || CPU(X86_64)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
@@ -1906,7 +2149,7 @@ void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&)
     ASSERT_NOT_REACHED();
 }
 
     ASSERT_NOT_REACHED();
 }
 
-#endif // PLATFORM(X86) || PLATFORM(X86_64)
+#endif // CPU(X86) || CPU(X86_64)
 
 /* ------------------------------ END: OP_MOD ------------------------------ */
 
 
 /* ------------------------------ END: OP_MOD ------------------------------ */
 
@@ -1931,55 +2174,87 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsign
     emitFastArithIntToImmNoCheck(regT0, regT0);
 }
 
     emitFastArithIntToImmNoCheck(regT0, regT0);
 }
 
-void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned result, unsigned op1, unsigned, OperandTypes types)
+void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned result, unsigned op1, unsigned op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase)
 {
     // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
     COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
 {
     // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
     COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
-
-    Jump notImm1 = getSlowCase(iter);
-    Jump notImm2 = getSlowCase(iter);
+    
+    Jump notImm1;
+    Jump notImm2;
+    if (op1HasImmediateIntFastCase) {
+        notImm2 = getSlowCase(iter);
+    } else if (op2HasImmediateIntFastCase) {
+        notImm1 = getSlowCase(iter);
+    } else {
+        notImm1 = getSlowCase(iter);
+        notImm2 = getSlowCase(iter);
+    }
 
     linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
 
     linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
-    if (opcodeID == op_mul) // op_mul has an extra slow case to handle 0 * negative number.
+    if (opcodeID == op_mul && !op1HasImmediateIntFastCase && !op2HasImmediateIntFastCase) // op_mul has an extra slow case to handle 0 * negative number.
         linkSlowCase(iter);
     emitGetVirtualRegister(op1, regT0);
 
     Label stubFunctionCall(this);
     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
         linkSlowCase(iter);
     emitGetVirtualRegister(op1, regT0);
 
     Label stubFunctionCall(this);
     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
+    if (op1HasImmediateIntFastCase || op2HasImmediateIntFastCase) {
+        emitGetVirtualRegister(op1, regT0);
+        emitGetVirtualRegister(op2, regT1);
+    }
     stubCall.addArgument(regT0);
     stubCall.addArgument(regT1);
     stubCall.call(result);
     Jump end = jump();
 
     stubCall.addArgument(regT0);
     stubCall.addArgument(regT1);
     stubCall.call(result);
     Jump end = jump();
 
-    // if we get here, eax is not an int32, edx not yet checked.
-    notImm1.link(this);
-    if (!types.first().definitelyIsNumber())
-        emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
-    if (!types.second().definitelyIsNumber())
-        emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
-    addPtr(tagTypeNumberRegister, regT0);
-    movePtrToDouble(regT0, fpRegT1);
-    Jump op2isDouble = emitJumpIfNotImmediateInteger(regT1);
-    convertInt32ToDouble(regT1, fpRegT2);
-    Jump op2wasInteger = jump();
-
-    // if we get here, eax IS an int32, edx is not.
-    notImm2.link(this);
-    if (!types.second().definitelyIsNumber())
-        emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
-    convertInt32ToDouble(regT0, fpRegT1);
-    op2isDouble.link(this);
-    addPtr(tagTypeNumberRegister, regT1);
-    movePtrToDouble(regT1, fpRegT2);
-    op2wasInteger.link(this);
+    if (op1HasImmediateIntFastCase) {
+        notImm2.link(this);
+        if (!types.second().definitelyIsNumber())
+            emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
+        emitGetVirtualRegister(op1, regT1);
+        convertInt32ToDouble(regT1, fpRegT1);
+        addPtr(tagTypeNumberRegister, regT0);
+        movePtrToDouble(regT0, fpRegT2);
+    } else if (op2HasImmediateIntFastCase) {
+        notImm1.link(this);
+        if (!types.first().definitelyIsNumber())
+            emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
+        emitGetVirtualRegister(op2, regT1);
+        convertInt32ToDouble(regT1, fpRegT1);
+        addPtr(tagTypeNumberRegister, regT0);
+        movePtrToDouble(regT0, fpRegT2);
+    } else {
+        // if we get here, eax is not an int32, edx not yet checked.
+        notImm1.link(this);
+        if (!types.first().definitelyIsNumber())
+            emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
+        if (!types.second().definitelyIsNumber())
+            emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
+        addPtr(tagTypeNumberRegister, regT0);
+        movePtrToDouble(regT0, fpRegT1);
+        Jump op2isDouble = emitJumpIfNotImmediateInteger(regT1);
+        convertInt32ToDouble(regT1, fpRegT2);
+        Jump op2wasInteger = jump();
+
+        // if we get here, eax IS an int32, edx is not.
+        notImm2.link(this);
+        if (!types.second().definitelyIsNumber())
+            emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
+        convertInt32ToDouble(regT0, fpRegT1);
+        op2isDouble.link(this);
+        addPtr(tagTypeNumberRegister, regT1);
+        movePtrToDouble(regT1, fpRegT2);
+        op2wasInteger.link(this);
+    }
 
     if (opcodeID == op_add)
         addDouble(fpRegT2, fpRegT1);
     else if (opcodeID == op_sub)
         subDouble(fpRegT2, fpRegT1);
 
     if (opcodeID == op_add)
         addDouble(fpRegT2, fpRegT1);
     else if (opcodeID == op_sub)
         subDouble(fpRegT2, fpRegT1);
-    else {
-        ASSERT(opcodeID == op_mul);
+    else if (opcodeID == op_mul)
         mulDouble(fpRegT2, fpRegT1);
         mulDouble(fpRegT2, fpRegT1);
+    else {
+        ASSERT(opcodeID == op_div);
+        divDouble(fpRegT2, fpRegT1);
     }
     moveDoubleToPtr(fpRegT1, regT0);
     subPtr(tagTypeNumberRegister, regT0);
     }
     moveDoubleToPtr(fpRegT1, regT0);
     subPtr(tagTypeNumberRegister, regT0);
@@ -2024,16 +2299,14 @@ void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>
     unsigned result = currentInstruction[1].u.operand;
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
     unsigned result = currentInstruction[1].u.operand;
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
+    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
 
-    if (isOperandConstantImmediateInt(op1) || isOperandConstantImmediateInt(op2)) {
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_add);
-        stubCall.addArgument(op1, regT2);
-        stubCall.addArgument(op2, regT2);
-        stubCall.call(result);
-    } else
-        compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
+    if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
+        return;
+
+    bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1);
+    bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2);
+    compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
 }
 
 void JIT::emit_op_mul(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_mul(Instruction* currentInstruction)
@@ -2068,17 +2341,89 @@ void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
-    if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))
-        || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
-        JITStubCall stubCall(this, cti_op_mul);
-        stubCall.addArgument(op1, regT2);
-        stubCall.addArgument(op2, regT2);
-        stubCall.call(result);
-    } else
-        compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, types);
+    bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1) && getConstantOperandImmediateInt(op1) > 0;
+    bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2) && getConstantOperandImmediateInt(op2) > 0;
+    compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
+}
+
+void JIT::emit_op_div(Instruction* currentInstruction)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned op1 = currentInstruction[2].u.operand;
+    unsigned op2 = currentInstruction[3].u.operand;
+    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+    if (isOperandConstantImmediateDouble(op1)) {
+        emitGetVirtualRegister(op1, regT0);
+        addPtr(tagTypeNumberRegister, regT0);
+        movePtrToDouble(regT0, fpRegT0);
+    } else if (isOperandConstantImmediateInt(op1)) {
+        emitLoadInt32ToDouble(op1, fpRegT0);
+    } else {
+        emitGetVirtualRegister(op1, regT0);
+        if (!types.first().definitelyIsNumber())
+            emitJumpSlowCaseIfNotImmediateNumber(regT0);
+        Jump notInt = emitJumpIfNotImmediateInteger(regT0);
+        convertInt32ToDouble(regT0, fpRegT0);
+        Jump skipDoubleLoad = jump();
+        notInt.link(this);
+        addPtr(tagTypeNumberRegister, regT0);
+        movePtrToDouble(regT0, fpRegT0);
+        skipDoubleLoad.link(this);
+    }
+    
+    if (isOperandConstantImmediateDouble(op2)) {
+        emitGetVirtualRegister(op2, regT1);
+        addPtr(tagTypeNumberRegister, regT1);
+        movePtrToDouble(regT1, fpRegT1);
+    } else if (isOperandConstantImmediateInt(op2)) {
+        emitLoadInt32ToDouble(op2, fpRegT1);
+    } else {
+        emitGetVirtualRegister(op2, regT1);
+        if (!types.second().definitelyIsNumber())
+            emitJumpSlowCaseIfNotImmediateNumber(regT1);
+        Jump notInt = emitJumpIfNotImmediateInteger(regT1);
+        convertInt32ToDouble(regT1, fpRegT1);
+        Jump skipDoubleLoad = jump();
+        notInt.link(this);
+        addPtr(tagTypeNumberRegister, regT1);
+        movePtrToDouble(regT1, fpRegT1);
+        skipDoubleLoad.link(this);
+    }
+    divDouble(fpRegT1, fpRegT0);
+
+    // Double result.
+    moveDoubleToPtr(fpRegT0, regT0);
+    subPtr(tagTypeNumberRegister, regT0);
+
+    emitPutVirtualRegister(dst, regT0);
+}
+
+void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned result = currentInstruction[1].u.operand;
+    unsigned op1 = currentInstruction[2].u.operand;
+    unsigned op2 = currentInstruction[3].u.operand;
+    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+    if (types.first().definitelyIsNumber() && types.second().definitelyIsNumber()) {
+#ifndef NDEBUG
+        breakpoint();
+#endif
+        return;
+    }
+    if (!isOperandConstantImmediateDouble(op1) && !isOperandConstantImmediateInt(op1)) {
+        if (!types.first().definitelyIsNumber())
+            linkSlowCase(iter);
+    }
+    if (!isOperandConstantImmediateDouble(op2) && !isOperandConstantImmediateInt(op2)) {
+        if (!types.second().definitelyIsNumber())
+            linkSlowCase(iter);
+    }
+    // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
+    JITStubCall stubCall(this, cti_op_div);
+    stubCall.addArgument(op1, regT2);
+    stubCall.addArgument(op2, regT2);
+    stubCall.call(result);
 }
 
 void JIT::emit_op_sub(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_sub(Instruction* currentInstruction)
@@ -2089,7 +2434,6 @@ void JIT::emit_op_sub(Instruction* currentInstruction)
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     compileBinaryArithOp(op_sub, result, op1, op2, types);
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     compileBinaryArithOp(op_sub, result, op1, op2, types);
-
     emitPutVirtualRegister(result);
 }
 
     emitPutVirtualRegister(result);
 }
 
@@ -2100,7 +2444,7 @@ void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
-    compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types);
+    compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types, false, false);
 }
 
 #else // USE(JSVALUE64)
 }
 
 #else // USE(JSVALUE64)
@@ -2283,6 +2627,15 @@ void JIT::emit_op_add(Instruction* currentInstruction)
     unsigned result = currentInstruction[1].u.operand;
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
     unsigned result = currentInstruction[1].u.operand;
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
+    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+
+    if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
+        JITStubCall stubCall(this, cti_op_add);
+        stubCall.addArgument(op1, regT2);
+        stubCall.addArgument(op2, regT2);
+        stubCall.call(result);
+        return;
+    }
 
     if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT0);
 
     if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT0);
@@ -2297,15 +2650,7 @@ void JIT::emit_op_add(Instruction* currentInstruction)
         signExtend32ToPtr(regT0, regT0);
         emitPutVirtualRegister(result);
     } else {
         signExtend32ToPtr(regT0, regT0);
         emitPutVirtualRegister(result);
     } else {
-        OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
-        if (types.first().mightBeNumber() && types.second().mightBeNumber())
-            compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
-        else {
-            JITStubCall stubCall(this, cti_op_add);
-            stubCall.addArgument(op1, regT2);
-            stubCall.addArgument(op2, regT2);
-            stubCall.call(result);
-        }
+        compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
     }
 }
 
     }
 }
 
@@ -2315,6 +2660,10 @@ void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
 
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
 
+    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
+    if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
+        return;
+
     if (isOperandConstantImmediateInt(op1)) {
         Jump notImm = getSlowCase(iter);
         linkSlowCase(iter);
     if (isOperandConstantImmediateInt(op1)) {
         Jump notImm = getSlowCase(iter);
         linkSlowCase(iter);
index fb1f2e1e34f13a16d29719b3acd8a2439715614c..179aad769a749f6fd02e3f20bf10a583f52e1429 100644 (file)
@@ -64,10 +64,9 @@ void JIT::compileOpCallSetupArgs(Instruction* instruction)
     int argCount = instruction[3].u.operand;
     int registerOffset = instruction[4].u.operand;
 
     int argCount = instruction[3].u.operand;
     int registerOffset = instruction[4].u.operand;
 
-    emitPutJITStubArg(regT0, 1);
-    emitPutJITStubArg(regT1, 2);
-    emitPutJITStubArgConstant(registerOffset, 3);
-    emitPutJITStubArgConstant(argCount, 5);
+    emitPutJITStubArg(regT1, regT0, 0);
+    emitPutJITStubArgConstant(registerOffset, 1);
+    emitPutJITStubArgConstant(argCount, 2);
 }
           
 void JIT::compileOpConstructSetupArgs(Instruction* instruction)
 }
           
 void JIT::compileOpConstructSetupArgs(Instruction* instruction)
@@ -77,20 +76,18 @@ void JIT::compileOpConstructSetupArgs(Instruction* instruction)
     int proto = instruction[5].u.operand;
     int thisRegister = instruction[6].u.operand;
 
     int proto = instruction[5].u.operand;
     int thisRegister = instruction[6].u.operand;
 
-    emitPutJITStubArg(regT0, 1);
-    emitPutJITStubArg(regT1, 2);
-    emitPutJITStubArgConstant(registerOffset, 3);
-    emitPutJITStubArgConstant(argCount, 5);
-    emitPutJITStubArgFromVirtualRegister(proto, 7, regT2, regT3);
-    emitPutJITStubArgConstant(thisRegister, 9);
+    emitPutJITStubArg(regT1, regT0, 0);
+    emitPutJITStubArgConstant(registerOffset, 1);
+    emitPutJITStubArgConstant(argCount, 2);
+    emitPutJITStubArgFromVirtualRegister(proto, 3, regT2, regT3);
+    emitPutJITStubArgConstant(thisRegister, 4);
 }
 
 void JIT::compileOpCallVarargsSetupArgs(Instruction*)
 {
 }
 
 void JIT::compileOpCallVarargsSetupArgs(Instruction*)
 {
-    emitPutJITStubArg(regT0, 1);
-    emitPutJITStubArg(regT1, 2);
-    emitPutJITStubArg(regT3, 3); // registerOffset
-    emitPutJITStubArg(regT2, 5); // argCount
+    emitPutJITStubArg(regT1, regT0, 0);
+    emitPutJITStubArg(regT3, 1); // registerOffset
+    emitPutJITStubArg(regT2, 2); // argCount
 }
 
 void JIT::compileOpCallVarargs(Instruction* instruction)
 }
 
 void JIT::compileOpCallVarargs(Instruction* instruction)
@@ -239,19 +236,17 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
     int argCount = instruction[3].u.operand;
     int registerOffset = instruction[4].u.operand;
 
     int argCount = instruction[3].u.operand;
     int registerOffset = instruction[4].u.operand;
 
-    Jump wasEval1;
-    Jump wasEval2;
+    Jump wasEval;
     if (opcodeID == op_call_eval) {
         JITStubCall stubCall(this, cti_op_call_eval);
         stubCall.addArgument(callee);
         stubCall.addArgument(JIT::Imm32(registerOffset));
         stubCall.addArgument(JIT::Imm32(argCount));
         stubCall.call();
     if (opcodeID == op_call_eval) {
         JITStubCall stubCall(this, cti_op_call_eval);
         stubCall.addArgument(callee);
         stubCall.addArgument(JIT::Imm32(registerOffset));
         stubCall.addArgument(JIT::Imm32(argCount));
         stubCall.call();
-        wasEval1 = branchTest32(NonZero, regT0);
-        wasEval2 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+        wasEval = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag));
     }
 
     }
 
-    emitLoad(callee, regT1, regT2);
+    emitLoad(callee, regT1, regT0);
 
     if (opcodeID == op_call)
         compileOpCallSetupArgs(instruction);
 
     if (opcodeID == op_call)
         compileOpCallSetupArgs(instruction);
@@ -259,12 +254,12 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
         compileOpConstructSetupArgs(instruction);
 
     emitJumpSlowCaseIfNotJSCell(callee, regT1);
         compileOpConstructSetupArgs(instruction);
 
     emitJumpSlowCaseIfNotJSCell(callee, regT1);
-    addSlowCase(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsFunctionVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr)));
 
     // First, in the case of a construct, allocate the new object.
     if (opcodeID == op_construct) {
         JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
 
     // First, in the case of a construct, allocate the new object.
     if (opcodeID == op_construct) {
         JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
-        emitLoad(callee, regT1, regT2);
+        emitLoad(callee, regT1, regT0);
     }
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
     }
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
@@ -274,12 +269,10 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
 
     emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
 
 
     emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
 
-    if (opcodeID == op_call_eval) {
-        wasEval1.link(this);
-        wasEval2.link(this);
-    }
+    if (opcodeID == op_call_eval)
+        wasEval.link(this);
 
 
-    emitStore(dst, regT1, regT0);;
+    emitStore(dst, regT1, regT0);
 
     sampleCodeBlock(m_codeBlock);
 }
 
     sampleCodeBlock(m_codeBlock);
 }
@@ -309,22 +302,26 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
     int argCount = instruction[3].u.operand;
     int registerOffset = instruction[4].u.operand;
 
     int argCount = instruction[3].u.operand;
     int registerOffset = instruction[4].u.operand;
 
-    Jump wasEval1;
-    Jump wasEval2;
+    Jump wasEval;
     if (opcodeID == op_call_eval) {
         JITStubCall stubCall(this, cti_op_call_eval);
         stubCall.addArgument(callee);
         stubCall.addArgument(JIT::Imm32(registerOffset));
         stubCall.addArgument(JIT::Imm32(argCount));
         stubCall.call();
     if (opcodeID == op_call_eval) {
         JITStubCall stubCall(this, cti_op_call_eval);
         stubCall.addArgument(callee);
         stubCall.addArgument(JIT::Imm32(registerOffset));
         stubCall.addArgument(JIT::Imm32(argCount));
         stubCall.call();
-        wasEval1 = branchTest32(NonZero, regT0);
-        wasEval2 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+        wasEval = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag));
     }
 
     emitLoad(callee, regT1, regT0);
 
     DataLabelPtr addressOfLinkedFunctionCheck;
     }
 
     emitLoad(callee, regT1, regT0);
 
     DataLabelPtr addressOfLinkedFunctionCheck;
+
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
+
     Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, ImmPtr(0));
     Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, ImmPtr(0));
+
+    END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
+
     addSlowCase(jumpToSlow);
     ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump);
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
     addSlowCase(jumpToSlow);
     ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump);
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
@@ -362,10 +359,8 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
     // Call to the callee
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
     
     // Call to the callee
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
     
-    if (opcodeID == op_call_eval) {
-        wasEval1.link(this);
-        wasEval2.link(this);
-    }
+    if (opcodeID == op_call_eval)
+        wasEval.link(this);
 
     // Put the return value in dst. In the interpreter, op_ret does this.
     emitStore(dst, regT1, regT0);
 
     // Put the return value in dst. In the interpreter, op_ret does this.
     emitStore(dst, regT1, regT0);
@@ -405,7 +400,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
     addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
     move(Imm32(argCount), regT1);
 
     addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
     move(Imm32(argCount), regT1);
 
-    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_globalData->jitStubs.ctiVirtualCallPreLink());
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_globalData->jitStubs.ctiVirtualCallLink());
 
     // Put the return value in dst.
     emitStore(dst, regT1, regT0);;
 
     // Put the return value in dst.
     emitStore(dst, regT1, regT0);;
@@ -439,10 +434,10 @@ void JIT::compileOpCallInitializeCallFrame()
 {
     store32(regT1, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))));
 
 {
     store32(regT1, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))));
 
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // newScopeChain
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // newScopeChain
 
     storePtr(ImmPtr(JSValue::encode(JSValue())), Address(callFrameRegister, RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register))));
 
     storePtr(ImmPtr(JSValue::encode(JSValue())), Address(callFrameRegister, RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register))));
-    storePtr(regT2, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register))));
+    storePtr(regT0, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register))));
     storePtr(regT1, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register))));
 }
 
     storePtr(regT1, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register))));
 }
 
@@ -452,9 +447,9 @@ void JIT::compileOpCallSetupArgs(Instruction* instruction)
     int registerOffset = instruction[4].u.operand;
 
     // ecx holds func
     int registerOffset = instruction[4].u.operand;
 
     // ecx holds func
-    emitPutJITStubArg(regT2, 1);
-    emitPutJITStubArgConstant(argCount, 3);
-    emitPutJITStubArgConstant(registerOffset, 2);
+    emitPutJITStubArg(regT0, 0);
+    emitPutJITStubArgConstant(argCount, 2);
+    emitPutJITStubArgConstant(registerOffset, 1);
 }
           
 void JIT::compileOpCallVarargsSetupArgs(Instruction* instruction)
 }
           
 void JIT::compileOpCallVarargsSetupArgs(Instruction* instruction)
@@ -462,10 +457,10 @@ void JIT::compileOpCallVarargsSetupArgs(Instruction* instruction)
     int registerOffset = instruction[4].u.operand;
     
     // ecx holds func
     int registerOffset = instruction[4].u.operand;
     
     // ecx holds func
+    emitPutJITStubArg(regT0, 0);
+    emitPutJITStubArg(regT1, 2);
+    addPtr(Imm32(registerOffset), regT1, regT2);
     emitPutJITStubArg(regT2, 1);
     emitPutJITStubArg(regT2, 1);
-    emitPutJITStubArg(regT1, 3);
-    addPtr(Imm32(registerOffset), regT1, regT0);
-    emitPutJITStubArg(regT0, 2);
 }
 
 void JIT::compileOpConstructSetupArgs(Instruction* instruction)
 }
 
 void JIT::compileOpConstructSetupArgs(Instruction* instruction)
@@ -476,11 +471,11 @@ void JIT::compileOpConstructSetupArgs(Instruction* instruction)
     int thisRegister = instruction[6].u.operand;
 
     // ecx holds func
     int thisRegister = instruction[6].u.operand;
 
     // ecx holds func
-    emitPutJITStubArg(regT2, 1);
-    emitPutJITStubArgConstant(registerOffset, 2);
-    emitPutJITStubArgConstant(argCount, 3);
-    emitPutJITStubArgFromVirtualRegister(proto, 4, regT0);
-    emitPutJITStubArgConstant(thisRegister, 5);
+    emitPutJITStubArg(regT0, 0);
+    emitPutJITStubArgConstant(registerOffset, 1);
+    emitPutJITStubArgConstant(argCount, 2);
+    emitPutJITStubArgFromVirtualRegister(proto, 3, regT2);
+    emitPutJITStubArgConstant(thisRegister, 4);
 }
 
 void JIT::compileOpCallVarargs(Instruction* instruction)
 }
 
 void JIT::compileOpCallVarargs(Instruction* instruction)
@@ -490,20 +485,20 @@ void JIT::compileOpCallVarargs(Instruction* instruction)
     int argCountRegister = instruction[3].u.operand;
 
     emitGetVirtualRegister(argCountRegister, regT1);
     int argCountRegister = instruction[3].u.operand;
 
     emitGetVirtualRegister(argCountRegister, regT1);
-    emitGetVirtualRegister(callee, regT2);
+    emitGetVirtualRegister(callee, regT0);
     compileOpCallVarargsSetupArgs(instruction);
 
     // Check for JSFunctions.
     compileOpCallVarargsSetupArgs(instruction);
 
     // Check for JSFunctions.
-    emitJumpSlowCaseIfNotJSCell(regT2);
-    addSlowCase(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsFunctionVPtr)));
-    
+    emitJumpSlowCaseIfNotJSCell(regT0);
+    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr)));
+
     // Speculatively roll the callframe, assuming argCount will match the arity.
     // Speculatively roll the callframe, assuming argCount will match the arity.
-    mul32(Imm32(sizeof(Register)), regT0, regT0);
+    mul32(Imm32(sizeof(Register)), regT2, regT2);
     intptr_t offset = (intptr_t)sizeof(Register) * (intptr_t)RegisterFile::CallerFrame;
     intptr_t offset = (intptr_t)sizeof(Register) * (intptr_t)RegisterFile::CallerFrame;
-    addPtr(Imm32((int32_t)offset), regT0, regT3);
+    addPtr(Imm32((int32_t)offset), regT2, regT3);
     addPtr(callFrameRegister, regT3);
     storePtr(callFrameRegister, regT3);
     addPtr(callFrameRegister, regT3);
     storePtr(callFrameRegister, regT3);
-    addPtr(regT0, callFrameRegister);
+    addPtr(regT2, callFrameRegister);
     emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
 
     // Put the return value in dst. In the interpreter, op_ret does this.
     emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
 
     // Put the return value in dst. In the interpreter, op_ret does this.
@@ -539,14 +534,14 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
     Jump wasEval;
     if (opcodeID == op_call_eval) {
         JITStubCall stubCall(this, cti_op_call_eval);
     Jump wasEval;
     if (opcodeID == op_call_eval) {
         JITStubCall stubCall(this, cti_op_call_eval);
-        stubCall.addArgument(callee, regT2);
+        stubCall.addArgument(callee, regT0);
         stubCall.addArgument(JIT::Imm32(registerOffset));
         stubCall.addArgument(JIT::Imm32(argCount));
         stubCall.call();
         wasEval = branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue())));
     }
 
         stubCall.addArgument(JIT::Imm32(registerOffset));
         stubCall.addArgument(JIT::Imm32(argCount));
         stubCall.call();
         wasEval = branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue())));
     }
 
-    emitGetVirtualRegister(callee, regT2);
+    emitGetVirtualRegister(callee, regT0);
     // The arguments have been set up on the hot path for op_call_eval
     if (opcodeID == op_call)
         compileOpCallSetupArgs(instruction);
     // The arguments have been set up on the hot path for op_call_eval
     if (opcodeID == op_call)
         compileOpCallSetupArgs(instruction);
@@ -554,13 +549,13 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
         compileOpConstructSetupArgs(instruction);
 
     // Check for JSFunctions.
         compileOpConstructSetupArgs(instruction);
 
     // Check for JSFunctions.
-    emitJumpSlowCaseIfNotJSCell(regT2);
-    addSlowCase(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsFunctionVPtr)));
+    emitJumpSlowCaseIfNotJSCell(regT0);
+    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr)));
 
     // First, in the case of a construct, allocate the new object.
     if (opcodeID == op_construct) {
         JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
 
     // First, in the case of a construct, allocate the new object.
     if (opcodeID == op_construct) {
         JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
-        emitGetVirtualRegister(callee, regT2);
+        emitGetVirtualRegister(callee, regT0);
     }
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
     }
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
@@ -606,7 +601,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
     Jump wasEval;
     if (opcodeID == op_call_eval) {
         JITStubCall stubCall(this, cti_op_call_eval);
     Jump wasEval;
     if (opcodeID == op_call_eval) {
         JITStubCall stubCall(this, cti_op_call_eval);
-        stubCall.addArgument(callee, regT2);
+        stubCall.addArgument(callee, regT0);
         stubCall.addArgument(JIT::Imm32(registerOffset));
         stubCall.addArgument(JIT::Imm32(argCount));
         stubCall.call();
         stubCall.addArgument(JIT::Imm32(registerOffset));
         stubCall.addArgument(JIT::Imm32(argCount));
         stubCall.call();
@@ -615,11 +610,17 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
 
     // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee.
     // This deliberately leaves the callee in ecx, used when setting up the stack frame below
 
     // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee.
     // This deliberately leaves the callee in ecx, used when setting up the stack frame below
-    emitGetVirtualRegister(callee, regT2);
+    emitGetVirtualRegister(callee, regT0);
     DataLabelPtr addressOfLinkedFunctionCheck;
     DataLabelPtr addressOfLinkedFunctionCheck;
-    Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT2, addressOfLinkedFunctionCheck, ImmPtr(JSValue::encode(JSValue())));
+
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
+
+    Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, ImmPtr(JSValue::encode(JSValue())));
+
+    END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
+
     addSlowCase(jumpToSlow);
     addSlowCase(jumpToSlow);
-    ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump);
+    ASSERT_JIT_OFFSET(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow), patchOffsetOpCallCompareToJump);
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
 
     // The following is the fast case, only used whan a callee can be linked.
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
 
     // The following is the fast case, only used whan a callee can be linked.
@@ -629,18 +630,18 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
         int proto = instruction[5].u.operand;
         int thisRegister = instruction[6].u.operand;
 
         int proto = instruction[5].u.operand;
         int thisRegister = instruction[6].u.operand;
 
-        emitPutJITStubArg(regT2, 1);
-        emitPutJITStubArgFromVirtualRegister(proto, 4, regT0);
+        emitPutJITStubArg(regT0, 0);
+        emitPutJITStubArgFromVirtualRegister(proto, 3, regT2);
         JITStubCall stubCall(this, cti_op_construct_JSConstruct);
         stubCall.call(thisRegister);
         JITStubCall stubCall(this, cti_op_construct_JSConstruct);
         stubCall.call(thisRegister);
-        emitGetVirtualRegister(callee, regT2);
+        emitGetVirtualRegister(callee, regT0);
     }
 
     // Fast version of stack frame initialization, directly relative to edi.
     // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee
     storePtr(ImmPtr(JSValue::encode(JSValue())), Address(callFrameRegister, (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast<int>(sizeof(Register))));
     }
 
     // Fast version of stack frame initialization, directly relative to edi.
     // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee
     storePtr(ImmPtr(JSValue::encode(JSValue())), Address(callFrameRegister, (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast<int>(sizeof(Register))));
-    storePtr(regT2, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register))));
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // newScopeChain
+    storePtr(regT0, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register))));
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // newScopeChain
     store32(Imm32(argCount), Address(callFrameRegister, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register))));
     storePtr(callFrameRegister, Address(callFrameRegister, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register))));
     storePtr(regT1, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register))));
     store32(Imm32(argCount), Address(callFrameRegister, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register))));
     storePtr(callFrameRegister, Address(callFrameRegister, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register))));
     storePtr(regT1, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register))));
@@ -674,13 +675,13 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
         compileOpConstructSetupArgs(instruction);
 
     // Fast check for JS function.
         compileOpConstructSetupArgs(instruction);
 
     // Fast check for JS function.
-    Jump callLinkFailNotObject = emitJumpIfNotJSCell(regT2);
-    Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsFunctionVPtr));
+    Jump callLinkFailNotObject = emitJumpIfNotJSCell(regT0);
+    Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr));
 
     // First, in the case of a construct, allocate the new object.
     if (opcodeID == op_construct) {
         JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
 
     // First, in the case of a construct, allocate the new object.
     if (opcodeID == op_construct) {
         JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
-        emitGetVirtualRegister(callee, regT2);
+        emitGetVirtualRegister(callee, regT0);
     }
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
     }
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
@@ -688,7 +689,9 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
     addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
     move(Imm32(argCount), regT1);
 
     addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
     move(Imm32(argCount), regT1);
 
-    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_globalData->jitStubs.ctiVirtualCallPreLink());
+    move(regT0, regT2);
+
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_globalData->jitStubs.ctiVirtualCallLink());
 
     // Put the return value in dst.
     emitPutVirtualRegister(dst);
 
     // Put the return value in dst.
     emitPutVirtualRegister(dst);
index b502c8a6727bf687072c95197f7638cdadd5c9a2..69cf16728e22c6104c81057f96be053b6ef485fe 100644 (file)
@@ -76,11 +76,7 @@ namespace JSC {
         // Execute the code!
         inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValue* exception)
         {
         // Execute the code!
         inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValue* exception)
         {
-            return JSValue::decode(ctiTrampoline(
-#if PLATFORM(X86_64)
-                0, 0, 0, 0, 0, 0,
-#endif
-                m_ref.m_code.executableAddress(), registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData));
+            return JSValue::decode(ctiTrampoline(m_ref.m_code.executableAddress(), registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData));
         }
 
         void* start()
         }
 
         void* start()
index c22a6921a523af364a5f249ae67bd995a8e871b1..5af756529d68f8573adb586373e21102a1031172 100644 (file)
@@ -37,28 +37,37 @@ namespace JSC {
 // puts an arg onto the stack, as an arg to a context threaded function.
 ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumber)
 {
 // puts an arg onto the stack, as an arg to a context threaded function.
 ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumber)
 {
-    poke(src, argumentNumber);
+    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
+    poke(src, argumentStackOffset);
 }
 
 /* Deprecated: Please use JITStubCall instead. */
 
 ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber)
 {
 }
 
 /* Deprecated: Please use JITStubCall instead. */
 
 ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber)
 {
-    poke(Imm32(value), argumentNumber);
+    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
+    poke(Imm32(value), argumentStackOffset);
 }
 
 /* Deprecated: Please use JITStubCall instead. */
 
 ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber)
 {
 }
 
 /* Deprecated: Please use JITStubCall instead. */
 
 ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber)
 {
-    poke(ImmPtr(value), argumentNumber);
+    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
+    poke(ImmPtr(value), argumentStackOffset);
 }
 
 /* Deprecated: Please use JITStubCall instead. */
 
 ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst)
 {
 }
 
 /* Deprecated: Please use JITStubCall instead. */
 
 ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst)
 {
-    peek(dst, argumentNumber);
+    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
+    peek(dst, argumentStackOffset);
+}
+
+ALWAYS_INLINE bool JIT::isOperandConstantImmediateDouble(unsigned src)
+{
+    return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isDouble();
 }
 
 ALWAYS_INLINE JSValue JIT::getConstantOperand(unsigned src)
 }
 
 ALWAYS_INLINE JSValue JIT::getConstantOperand(unsigned src)
@@ -102,38 +111,71 @@ ALWAYS_INLINE JIT::Call JIT::emitNakedCall(CodePtr function)
     return nakedCall;
 }
 
     return nakedCall;
 }
 
-#if PLATFORM(X86) || PLATFORM(X86_64)
+#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
+
+ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace)
+{
+#if CPU(ARM_TRADITIONAL)
+#ifndef NDEBUG
+    // Ensure the label after the sequence can also fit
+    insnSpace += sizeof(ARMWord);
+    constSpace += sizeof(uint64_t);
+#endif
+
+    ensureSpace(insnSpace, constSpace);
+
+#endif
+
+#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
+#ifndef NDEBUG
+    m_uninterruptedInstructionSequenceBegin = label();
+    m_uninterruptedConstantSequenceBegin = sizeOfConstantPool();
+#endif
+#endif
+}
+
+ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace)
+{
+#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
+    ASSERT(differenceBetween(m_uninterruptedInstructionSequenceBegin, label()) == insnSpace);
+    ASSERT(sizeOfConstantPool() - m_uninterruptedConstantSequenceBegin == constSpace);
+#endif
+}
+
+#endif
+
+#if CPU(ARM)
 
 ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
 {
 
 ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
 {
-    pop(reg);
+    move(linkRegister, reg);
 }
 
 ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
 {
 }
 
 ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
 {
-    push(reg);
+    move(reg, linkRegister);
 }
 
 ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 {
 }
 
 ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 {
-    push(address);
+    loadPtr(address, linkRegister);
 }
 
 }
 
-#elif PLATFORM_ARM_ARCH(7)
+#else // CPU(X86) || CPU(X86_64)
 
 ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
 {
 
 ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
 {
-    move(linkRegister, reg);
+    pop(reg);
 }
 
 ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
 {
 }
 
 ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
 {
-    move(reg, linkRegister);
+    push(reg);
 }
 
 ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 {
 }
 
 ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 {
-    loadPtr(address, linkRegister);
+    push(address);
 }
 
 #endif
 }
 
 #endif
@@ -152,10 +194,10 @@ ALWAYS_INLINE void JIT::restoreArgumentReference()
 }
 ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
 {
 }
 ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
 {
-#if PLATFORM(X86)
+#if CPU(X86)
     // Within a trampoline the return address will be on the stack at this point.
     addPtr(Imm32(sizeof(void*)), stackPointerRegister, firstArgumentRegister);
     // Within a trampoline the return address will be on the stack at this point.
     addPtr(Imm32(sizeof(void*)), stackPointerRegister, firstArgumentRegister);
-#elif PLATFORM_ARM_ARCH(7)
+#elif CPU(ARM)
     move(stackPointerRegister, firstArgumentRegister);
 #endif
     // In the trampoline on x86-64, the first argument register is not overwritten.
     move(stackPointerRegister, firstArgumentRegister);
 #endif
     // In the trampoline on x86-64, the first argument register is not overwritten.
@@ -223,9 +265,9 @@ ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag)
 #if ENABLE(SAMPLING_COUNTERS)
 ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t count)
 {
 #if ENABLE(SAMPLING_COUNTERS)
 ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t count)
 {
-#if PLATFORM(X86_64) // Or any other 64-bit plattform.
+#if CPU(X86_64) // Or any other 64-bit plattform.
     addPtr(Imm32(count), AbsoluteAddress(&counter.m_counter));
     addPtr(Imm32(count), AbsoluteAddress(&counter.m_counter));
-#elif PLATFORM(X86) // Or any other little-endian 32-bit plattform.
+#elif CPU(X86) // Or any other little-endian 32-bit plattform.
     intptr_t hiWord = reinterpret_cast<intptr_t>(&counter.m_counter) + sizeof(int32_t);
     add32(Imm32(count), AbsoluteAddress(&counter.m_counter));
     addWithCarry32(Imm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord)));
     intptr_t hiWord = reinterpret_cast<intptr_t>(&counter.m_counter) + sizeof(int32_t);
     add32(Imm32(count), AbsoluteAddress(&counter.m_counter));
     addWithCarry32(Imm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord)));
@@ -236,11 +278,11 @@ ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t cou
 #endif
 
 #if ENABLE(OPCODE_SAMPLING)
 #endif
 
 #if ENABLE(OPCODE_SAMPLING)
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
 ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
 {
 ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
 {
-    move(ImmPtr(m_interpreter->sampler()->sampleSlot()), X86::ecx);
-    storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86::ecx);
+    move(ImmPtr(m_interpreter->sampler()->sampleSlot()), X86Registers::ecx);
+    storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86Registers::ecx);
 }
 #else
 ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
 }
 #else
 ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
@@ -251,11 +293,11 @@ ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostF
 #endif
 
 #if ENABLE(CODEBLOCK_SAMPLING)
 #endif
 
 #if ENABLE(CODEBLOCK_SAMPLING)
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
 ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
 {
 ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
 {
-    move(ImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86::ecx);
-    storePtr(ImmPtr(codeBlock), X86::ecx);
+    move(ImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86Registers::ecx);
+    storePtr(ImmPtr(codeBlock), X86Registers::ecx);
 }
 #else
 ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
 }
 #else
 ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
@@ -265,6 +307,11 @@ ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
 #endif
 #endif
 
 #endif
 #endif
 
+inline JIT::Address JIT::addressFor(unsigned index, RegisterID base)
+{
+    return Address(base, (index * sizeof(Register)));
+}
+
 #if USE(JSVALUE32_64)
 
 inline JIT::Address JIT::tagFor(unsigned index, RegisterID base)
 #if USE(JSVALUE32_64)
 
 inline JIT::Address JIT::tagFor(unsigned index, RegisterID base)
@@ -277,11 +324,6 @@ inline JIT::Address JIT::payloadFor(unsigned index, RegisterID base)
     return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
 }
 
     return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
 }
 
-inline JIT::Address JIT::addressFor(unsigned index, RegisterID base)
-{
-    return Address(base, (index * sizeof(Register)));
-}
-
 inline void JIT::emitLoadTag(unsigned index, RegisterID tag)
 {
     RegisterID mappedTag;
 inline void JIT::emitLoadTag(unsigned index, RegisterID tag)
 {
     RegisterID mappedTag;
@@ -539,23 +581,28 @@ ALWAYS_INLINE bool JIT::getOperandConstantImmediateInt(unsigned op1, unsigned op
     return false;
 }
 
     return false;
 }
 
-ALWAYS_INLINE bool JIT::isOperandConstantImmediateDouble(unsigned src)
+/* Deprecated: Please use JITStubCall instead. */
+
+ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID tag, RegisterID payload, unsigned argumentNumber)
 {
 {
-    return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isDouble();
+    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
+    poke(payload, argumentStackOffset);
+    poke(tag, argumentStackOffset + 1);
 }
 
 /* Deprecated: Please use JITStubCall instead. */
 
 ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2)
 {
 }
 
 /* Deprecated: Please use JITStubCall instead. */
 
 ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2)
 {
+    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
     if (m_codeBlock->isConstantRegisterIndex(src)) {
         JSValue constant = m_codeBlock->getConstant(src);
     if (m_codeBlock->isConstantRegisterIndex(src)) {
         JSValue constant = m_codeBlock->getConstant(src);
-        poke(Imm32(constant.payload()), argumentNumber);
-        poke(Imm32(constant.tag()), argumentNumber + 1);
+        poke(Imm32(constant.payload()), argumentStackOffset);
+        poke(Imm32(constant.tag()), argumentStackOffset + 1);
     } else {
         emitLoad(src, scratch1, scratch2);
     } else {
         emitLoad(src, scratch1, scratch2);
-        poke(scratch2, argumentNumber);
-        poke(scratch1, argumentNumber + 1);
+        poke(scratch2, argumentStackOffset);
+        poke(scratch1, argumentStackOffset + 1);
     }
 }
 
     }
 }
 
@@ -682,6 +729,24 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateNumber(RegisterID reg)
 {
     return branchTestPtr(Zero, reg, tagTypeNumberRegister);
 }
 {
     return branchTestPtr(Zero, reg, tagTypeNumberRegister);
 }
+
+inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
+{
+    if (m_codeBlock->isConstantRegisterIndex(index)) {
+        Register& inConstantPool = m_codeBlock->constantRegister(index);
+        loadDouble(&inConstantPool, value);
+    } else
+        loadDouble(addressFor(index), value);
+}
+
+inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
+{
+    if (m_codeBlock->isConstantRegisterIndex(index)) {
+        Register& inConstantPool = m_codeBlock->constantRegister(index);
+        convertInt32ToDouble(AbsoluteAddress(&inConstantPool), value);
+    } else
+        convertInt32ToDouble(addressFor(index), value);
+}
 #endif
 
 ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg)
 #endif
 
 ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg)
@@ -719,6 +784,11 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateIntegers(RegisterID reg1,
     addSlowCase(emitJumpIfNotImmediateIntegers(reg1, reg2, scratch));
 }
 
     addSlowCase(emitJumpIfNotImmediateIntegers(reg1, reg2, scratch));
 }
 
+ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateNumber(RegisterID reg)
+{
+    addSlowCase(emitJumpIfNotImmediateNumber(reg));
+}
+
 #if !USE(JSVALUE64)
 ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg)
 {
 #if !USE(JSVALUE64)
 ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg)
 {
@@ -747,7 +817,7 @@ ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg)
 #if USE(JSVALUE64)
     UNUSED_PARAM(reg);
 #else
 #if USE(JSVALUE64)
     UNUSED_PARAM(reg);
 #else
-    rshiftPtr(Imm32(JSImmediate::IntegerPayloadShift), reg);
+    rshift32(Imm32(JSImmediate::IntegerPayloadShift), reg);
 #endif
 }
 
 #endif
 }
 
@@ -776,12 +846,13 @@ ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg)
 // get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
 ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch)
 {
 // get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
 ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch)
 {
+    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
     if (m_codeBlock->isConstantRegisterIndex(src)) {
         JSValue value = m_codeBlock->getConstant(src);
     if (m_codeBlock->isConstantRegisterIndex(src)) {
         JSValue value = m_codeBlock->getConstant(src);
-        emitPutJITStubArgConstant(JSValue::encode(value), argumentNumber);
+        poke(ImmPtr(JSValue::encode(value)), argumentStackOffset);
     } else {
         loadPtr(Address(callFrameRegister, src * sizeof(Register)), scratch);
     } else {
         loadPtr(Address(callFrameRegister, src * sizeof(Register)), scratch);
-        emitPutJITStubArg(scratch, argumentNumber);
+        poke(scratch, argumentStackOffset);
     }
 
     killLastResultRegister();
     }
 
     killLastResultRegister();
index 85997c2de308bc34bebb0e56621ad58f04064a26..d9a32d9ae39c6649067bb0909b14f749c3d49515 100644 (file)
 #include "JSArray.h"
 #include "JSCell.h"
 #include "JSFunction.h"
 #include "JSArray.h"
 #include "JSCell.h"
 #include "JSFunction.h"
+#include "JSPropertyNameIterator.h"
 #include "LinkBuffer.h"
 
 namespace JSC {
 
 #if USE(JSVALUE32_64)
 
 #include "LinkBuffer.h"
 
 namespace JSC {
 
 #if USE(JSVALUE32_64)
 
-void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallPreLink, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
+void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
 {
 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
     // (1) This function provides fast property access for string length
 {
 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
     // (1) This function provides fast property access for string length
@@ -51,8 +52,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
 
     // Checks out okay! - get the length from the Ustring.
     Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
 
     // Checks out okay! - get the length from the Ustring.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSString, m_value) + OBJECT_OFFSETOF(UString, m_rep)), regT2);
-    load32(Address(regT2, OBJECT_OFFSETOF(UString::Rep, len)), regT2);
+    load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_stringLength)), regT2);
 
     Jump string_failureCases3 = branch32(Above, regT2, Imm32(INT_MAX));
     move(regT2, regT0);
 
     Jump string_failureCases3 = branch32(Above, regT2, Imm32(INT_MAX));
     move(regT2, regT0);
@@ -64,138 +64,80 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     // (2) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
 
 #if ENABLE(JIT_OPTIMIZE_CALL)
     // (2) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
 
 #if ENABLE(JIT_OPTIMIZE_CALL)
-    /* VirtualCallPreLink Trampoline */
-    Label virtualCallPreLinkBegin = align();
-
-    // regT0 holds callee, regT1 holds argCount.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_body)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT2);
-    Jump hasCodeBlock1 = branchTestPtr(NonZero, regT2);
-
-    // Lazily generate a CodeBlock.
-    preserveReturnAddressAfterCall(regT3); // return address
-    restoreArgumentReference();
-    Call callJSFunction1 = call();
-    move(regT0, regT2);
-    emitGetJITStubArg(1, regT0); // callee
-    emitGetJITStubArg(5, regT1); // argCount
-    restoreReturnAddressBeforeReturn(regT3); // return address
-    hasCodeBlock1.link(this);
-
-    // regT2 holds codeBlock.
-    Jump isNativeFunc1 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
-
-    // Check argCount matches callee arity.
-    Jump arityCheckOkay1 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
-    preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 3); // return address
-    emitPutJITStubArg(regT2, 7); // codeBlock
-    restoreArgumentReference();
-    Call callArityCheck1 = call();
-    move(regT1, callFrameRegister);
-    emitGetJITStubArg(1, regT0); // callee
-    emitGetJITStubArg(5, regT1); // argCount
-    restoreReturnAddressBeforeReturn(regT3); // return address
-
-    arityCheckOkay1.link(this);
-    isNativeFunc1.link(this);
-    
-    compileOpCallInitializeCallFrame();
-
-    preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 3);
-    restoreArgumentReference();
-    Call callDontLazyLinkCall = call();
-    restoreReturnAddressBeforeReturn(regT3);
-    jump(regT0);
-
-    /* VirtualCallLink Trampoline */
+    // VirtualCallLink Trampoline
+    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
     Label virtualCallLinkBegin = align();
     Label virtualCallLinkBegin = align();
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
 
 
-    // regT0 holds callee, regT1 holds argCount.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_body)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT2);
-    Jump hasCodeBlock2 = branchTestPtr(NonZero, regT2);
+    Jump isNativeFunc2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
 
 
-    // Lazily generate a CodeBlock.
-    preserveReturnAddressAfterCall(regT3); // return address
+    Jump hasCodeBlock2 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
+    preserveReturnAddressAfterCall(regT3);
     restoreArgumentReference();
     Call callJSFunction2 = call();
     restoreArgumentReference();
     Call callJSFunction2 = call();
-    move(regT0, regT2);
-    emitGetJITStubArg(1, regT0); // callee
-    emitGetJITStubArg(5, regT1); // argCount
-    restoreReturnAddressBeforeReturn(regT3); // return address
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    emitGetJITStubArg(2, regT1); // argCount
+    restoreReturnAddressBeforeReturn(regT3);
     hasCodeBlock2.link(this);
 
     hasCodeBlock2.link(this);
 
-    // regT2 holds codeBlock.
-    Jump isNativeFunc2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
-
     // Check argCount matches callee arity.
     // Check argCount matches callee arity.
-    Jump arityCheckOkay2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
+    Jump arityCheckOkay2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
     preserveReturnAddressAfterCall(regT3);
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 3); // return address
-    emitPutJITStubArg(regT2, 7); // codeBlock
+    emitPutJITStubArg(regT3, 1); // return address
     restoreArgumentReference();
     Call callArityCheck2 = call();
     move(regT1, callFrameRegister);
     restoreArgumentReference();
     Call callArityCheck2 = call();
     move(regT1, callFrameRegister);
-    emitGetJITStubArg(1, regT0); // callee
-    emitGetJITStubArg(5, regT1); // argCount
-    restoreReturnAddressBeforeReturn(regT3); // return address
-
+    emitGetJITStubArg(2, regT1); // argCount
+    restoreReturnAddressBeforeReturn(regT3);
     arityCheckOkay2.link(this);
     arityCheckOkay2.link(this);
+
     isNativeFunc2.link(this);
 
     compileOpCallInitializeCallFrame();
 
     preserveReturnAddressAfterCall(regT3);
     isNativeFunc2.link(this);
 
     compileOpCallInitializeCallFrame();
 
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 3);
+    emitPutJITStubArg(regT3, 1); // return address
     restoreArgumentReference();
     Call callLazyLinkCall = call();
     restoreReturnAddressBeforeReturn(regT3);
     jump(regT0);
 #endif // ENABLE(JIT_OPTIMIZE_CALL)
 
     restoreArgumentReference();
     Call callLazyLinkCall = call();
     restoreReturnAddressBeforeReturn(regT3);
     jump(regT0);
 #endif // ENABLE(JIT_OPTIMIZE_CALL)
 
-    /* VirtualCall Trampoline */
+    // VirtualCall Trampoline
+    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
     Label virtualCallBegin = align();
     Label virtualCallBegin = align();
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
 
 
-    // regT0 holds callee, regT1 holds argCount.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_body)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT2);
-    Jump hasCodeBlock3 = branchTestPtr(NonZero, regT2);
+    Jump isNativeFunc3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
 
 
-    // Lazily generate a CodeBlock.
-    preserveReturnAddressAfterCall(regT3); // return address
+    Jump hasCodeBlock3 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
+    preserveReturnAddressAfterCall(regT3);
     restoreArgumentReference();
     restoreArgumentReference();
-    Call callJSFunction3 = call();
-    move(regT0, regT2);
-    emitGetJITStubArg(1, regT0); // callee
-    emitGetJITStubArg(5, regT1); // argCount
-    restoreReturnAddressBeforeReturn(regT3); // return address
+    Call callJSFunction1 = call();
+    emitGetJITStubArg(2, regT1); // argCount
+    restoreReturnAddressBeforeReturn(regT3);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
     hasCodeBlock3.link(this);
     
     hasCodeBlock3.link(this);
     
-    // regT2 holds codeBlock.
-    Jump isNativeFunc3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
-    
-    // Check argCount matches callee.
-    Jump arityCheckOkay3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
+    // Check argCount matches callee arity.
+    Jump arityCheckOkay3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
     preserveReturnAddressAfterCall(regT3);
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 3); // return address
-    emitPutJITStubArg(regT2, 7); // codeBlock
+    emitPutJITStubArg(regT3, 1); // return address
     restoreArgumentReference();
     restoreArgumentReference();
-    Call callArityCheck3 = call();
+    Call callArityCheck1 = call();
     move(regT1, callFrameRegister);
     move(regT1, callFrameRegister);
-    emitGetJITStubArg(1, regT0); // callee
-    emitGetJITStubArg(5, regT1); // argCount
-    restoreReturnAddressBeforeReturn(regT3); // return address
-
+    emitGetJITStubArg(2, regT1); // argCount
+    restoreReturnAddressBeforeReturn(regT3);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
     arityCheckOkay3.link(this);
     arityCheckOkay3.link(this);
+
     isNativeFunc3.link(this);
     isNativeFunc3.link(this);
+
     compileOpCallInitializeCallFrame();
     compileOpCallInitializeCallFrame();
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_body)), regT0);
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(FunctionBodyNode, m_jitCode)), regT0);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCode)), regT0);
     jump(regT0);
 
     jump(regT0);
 
-#if PLATFORM(X86)
+#if CPU(X86) || CPU(ARM_TRADITIONAL)
     Label nativeCallThunk = align();
     preserveReturnAddressAfterCall(regT0);
     emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address
     Label nativeCallThunk = align();
     preserveReturnAddressAfterCall(regT0);
     emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address
@@ -206,6 +148,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT1);
     emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
     
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT1);
     emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
     
+#if CPU(X86)
     emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
 
     /* We have two structs that we use to describe the stackframe we set up for our
     emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
 
     /* We have two structs that we use to describe the stackframe we set up for our
@@ -217,7 +160,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
      * stack pointer by the right amount after the call.
      */
 
      * stack pointer by the right amount after the call.
      */
 
-#if COMPILER(MSVC) || PLATFORM(LINUX)
+#if COMPILER(MSVC) || OS(LINUX)
 #if COMPILER(MSVC)
 #pragma pack(push)
 #pragma pack(4)
 #if COMPILER(MSVC)
 #pragma pack(push)
 #pragma pack(4)
@@ -280,36 +223,94 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     storePtr(regT2, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
     storePtr(regT3, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
 
     storePtr(regT2, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
     storePtr(regT3, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
 
-#if COMPILER(MSVC) || PLATFORM(LINUX)
+#if COMPILER(MSVC) || OS(LINUX)
     // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
     // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
-    addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86::ecx);
+    addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86Registers::ecx);
 
     // Plant callee
 
     // Plant callee
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86::eax);
-    storePtr(X86::eax, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, callee)));
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::eax);
+    storePtr(X86Registers::eax, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, callee)));
 
     // Plant callframe
 
     // Plant callframe
-    move(callFrameRegister, X86::edx);
+    move(callFrameRegister, X86Registers::edx);
 
 
-    call(Address(X86::eax, OBJECT_OFFSETOF(JSFunction, m_data)));
+    call(Address(X86Registers::eax, OBJECT_OFFSETOF(JSFunction, m_data)));
 
     // JSValue is a non-POD type, so eax points to it
 
     // JSValue is a non-POD type, so eax points to it
-    emitLoad(0, regT1, regT0, X86::eax);
+    emitLoad(0, regT1, regT0, X86Registers::eax);
 #else
 #else
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86::edx); // callee
-    move(callFrameRegister, X86::ecx); // callFrame
-    call(Address(X86::edx, OBJECT_OFFSETOF(JSFunction, m_data)));
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::edx); // callee
+    move(callFrameRegister, X86Registers::ecx); // callFrame
+    call(Address(X86Registers::edx, OBJECT_OFFSETOF(JSFunction, m_data)));
 #endif
 
     // We've put a few temporaries on the stack in addition to the actual arguments
     // so pull them off now
     addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister);
 
 #endif
 
     // We've put a few temporaries on the stack in addition to the actual arguments
     // so pull them off now
     addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister);
 
+#elif CPU(ARM_TRADITIONAL)
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+
+    // Allocate stack space for our arglist
+    COMPILE_ASSERT((sizeof(ArgList) & 0x7) == 0 && sizeof(JSValue) == 8 && sizeof(Register) == 8, ArgList_should_by_8byte_aligned);
+    subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
+
+    // Set up arguments
+    subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
+
+    // Push argcount
+    storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
+
+    // Calculate the start of the callframe header, and store in regT1
+    move(callFrameRegister, regT1);
+    sub32(Imm32(RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), regT1);
+
+    // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT1)
+    mul32(Imm32(sizeof(Register)), regT0, regT0);
+    subPtr(regT0, regT1);
+
+    // push pointer to arguments
+    storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
+
+    // Argument passing method:
+    // r0 - points to return value
+    // r1 - callFrame
+    // r2 - callee
+    // stack: this(JSValue) and a pointer to ArgList
+
+    move(stackPointerRegister, regT3);
+    subPtr(Imm32(8), stackPointerRegister);
+    move(stackPointerRegister, regT0);
+    subPtr(Imm32(8 + 4 + 4 /* padding */), stackPointerRegister);
+
+    // Setup arg4:
+    storePtr(regT3, Address(stackPointerRegister, 8));
+
+    // Setup arg3
+    // regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this'
+    load32(Address(regT1, -(int32_t)sizeof(void*) * 2), regT3);
+    storePtr(regT3, Address(stackPointerRegister, 0));
+    load32(Address(regT1, -(int32_t)sizeof(void*)), regT3);
+    storePtr(regT3, Address(stackPointerRegister, 4));
+
+    // Setup arg2:
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT2);
+
+    // Setup arg1:
+    move(callFrameRegister, regT1);
+
+    call(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data)));
+
+    // Load return value
+    load32(Address(stackPointerRegister, 16), regT0);
+    load32(Address(stackPointerRegister, 20), regT1);
+
+    addPtr(Imm32(sizeof(ArgList) + 16 + 8), stackPointerRegister);
+#endif
+
     // Check for an exception
     // Check for an exception
-    // FIXME: Maybe we can optimize this comparison to JSValue().
     move(ImmPtr(&globalData->exception), regT2);
     move(ImmPtr(&globalData->exception), regT2);
-    Jump sawException1 = branch32(NotEqual, tagFor(0, regT2), Imm32(JSValue::CellTag));
-    Jump sawException2 = branch32(NonZero, payloadFor(0, regT2), Imm32(0));
+    Jump sawException = branch32(NotEqual, tagFor(0, regT2), Imm32(JSValue::EmptyValueTag));
 
     // Grab the return address.
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT3);
 
     // Grab the return address.
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT3);
@@ -322,13 +323,12 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     ret();
 
     // Handle an exception
     ret();
 
     // Handle an exception
-    sawException1.link(this);
-    sawException2.link(this);
+    sawException.link(this);
     // Grab the return address.
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
     move(ImmPtr(&globalData->exceptionLocation), regT2);
     storePtr(regT1, regT2);
     // Grab the return address.
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
     move(ImmPtr(&globalData->exceptionLocation), regT2);
     storePtr(regT1, regT2);
-    move(ImmPtr(reinterpret_cast<void*>(ctiVMThrowTrampoline)), regT2);
+    move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
     restoreReturnAddressBeforeReturn(regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
     restoreReturnAddressBeforeReturn(regT2);
@@ -354,16 +354,13 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
     patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
 #endif
     patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
     patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
 #endif
-#if ENABLE(JIT_OPTIMIZE_CALL)
     patchBuffer.link(callArityCheck1, FunctionPtr(cti_op_call_arityCheck));
     patchBuffer.link(callJSFunction1, FunctionPtr(cti_op_call_JSFunction));
     patchBuffer.link(callArityCheck1, FunctionPtr(cti_op_call_arityCheck));
     patchBuffer.link(callJSFunction1, FunctionPtr(cti_op_call_JSFunction));
+#if ENABLE(JIT_OPTIMIZE_CALL)
     patchBuffer.link(callArityCheck2, FunctionPtr(cti_op_call_arityCheck));
     patchBuffer.link(callJSFunction2, FunctionPtr(cti_op_call_JSFunction));
     patchBuffer.link(callArityCheck2, FunctionPtr(cti_op_call_arityCheck));
     patchBuffer.link(callJSFunction2, FunctionPtr(cti_op_call_JSFunction));
-    patchBuffer.link(callDontLazyLinkCall, FunctionPtr(cti_vm_dontLazyLinkCall));
     patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
 #endif
     patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
 #endif
-    patchBuffer.link(callArityCheck3, FunctionPtr(cti_op_call_arityCheck));
-    patchBuffer.link(callJSFunction3, FunctionPtr(cti_op_call_JSFunction));
 
     CodeRef finalCode = patchBuffer.finalizeCode();
     *executablePool = finalCode.m_executablePool;
 
     CodeRef finalCode = patchBuffer.finalizeCode();
     *executablePool = finalCode.m_executablePool;
@@ -376,10 +373,8 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     UNUSED_PARAM(ctiStringLengthTrampoline);
 #endif
 #if ENABLE(JIT_OPTIMIZE_CALL)
     UNUSED_PARAM(ctiStringLengthTrampoline);
 #endif
 #if ENABLE(JIT_OPTIMIZE_CALL)
-    *ctiVirtualCallPreLink = trampolineAt(finalCode, virtualCallPreLinkBegin);
     *ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
 #else
     *ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
 #else
-    UNUSED_PARAM(ctiVirtualCallPreLink);
     UNUSED_PARAM(ctiVirtualCallLink);
 #endif
 }
     UNUSED_PARAM(ctiVirtualCallLink);
 #endif
 }
@@ -411,59 +406,7 @@ void JIT::emit_op_end(Instruction* currentInstruction)
 void JIT::emit_op_jmp(Instruction* currentInstruction)
 {
     unsigned target = currentInstruction[1].u.operand;
 void JIT::emit_op_jmp(Instruction* currentInstruction)
 {
     unsigned target = currentInstruction[1].u.operand;
-    addJump(jump(), target + 1);
-}
-
-void JIT::emit_op_loop(Instruction* currentInstruction)
-{
-    unsigned target = currentInstruction[1].u.operand;
-    emitTimeoutCheck();
-    addJump(jump(), target + 1);
-}
-
-void JIT::emit_op_loop_if_less(Instruction* currentInstruction)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    emitTimeoutCheck();
-
-    if (isOperandConstantImmediateInt(op1)) {
-        emitLoad(op2, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-        addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op1).asInt32())), target + 3);
-        return;
-    }
-    
-    if (isOperandConstantImmediateInt(op2)) {
-        emitLoad(op1, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-        addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3);
-        return;
-    }
-
-    emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
-    addJump(branch32(LessThan, regT0, regT2), target + 3);
-}
-
-void JIT::emitSlow_op_loop_if_less(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
-        linkSlowCase(iter); // int32 check
-    linkSlowCase(iter); // int32 check
-
-    JITStubCall stubCall(this, cti_op_loop_if_less);
-    stubCall.addArgument(op1);
-    stubCall.addArgument(op2);
-    stubCall.call();
-    emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+    addJump(jump(), target);
 }
 
 void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
@@ -477,21 +420,21 @@ void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op1).asInt32())), target + 3);
+        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op1).asInt32())), target);
         return;
     }
 
     if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
         return;
     }
 
     if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-        addJump(branch32(LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3);
+        addJump(branch32(LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
         return;
     }
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
         return;
     }
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
-    addJump(branch32(LessThanOrEqual, regT0, regT2), target + 3);
+    addJump(branch32(LessThanOrEqual, regT0, regT2), target);
 }
 
 void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -508,7 +451,7 @@ void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<Slo
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     stubCall.call();
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     stubCall.call();
-    emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+    emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
 }
 
 void JIT::emit_op_new_object(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_new_object(Instruction* currentInstruction)
@@ -523,30 +466,20 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
     unsigned baseVal = currentInstruction[3].u.operand;
     unsigned proto = currentInstruction[4].u.operand;
 
     unsigned baseVal = currentInstruction[3].u.operand;
     unsigned proto = currentInstruction[4].u.operand;
 
-    // Load the operands (baseVal, proto, and value respectively) into registers.
+    // Load the operands into registers.
     // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result.
     // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result.
-    emitLoadPayload(proto, regT1);
-    emitLoadPayload(baseVal, regT0);
     emitLoadPayload(value, regT2);
     emitLoadPayload(value, regT2);
+    emitLoadPayload(baseVal, regT0);
+    emitLoadPayload(proto, regT1);
 
 
-    // Check that baseVal & proto are cells.
-    emitJumpSlowCaseIfNotJSCell(proto);
+    // Check that value, baseVal, and proto are cells.
+    emitJumpSlowCaseIfNotJSCell(value);
     emitJumpSlowCaseIfNotJSCell(baseVal);
     emitJumpSlowCaseIfNotJSCell(baseVal);
+    emitJumpSlowCaseIfNotJSCell(proto);
 
 
-    // Check that baseVal is an object, that it 'ImplementsHasInstance' but that it does not 'OverridesHasInstance'.
+    // Check that baseVal 'ImplementsDefaultHasInstance'.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
-    addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); // FIXME: Maybe remove this test.
-    addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsHasInstance))); // FIXME: TOT checks ImplementsDefaultHasInstance.
-
-    // If value is not an Object, return false.
-    emitLoadTag(value, regT0);
-    Jump valueIsImmediate = branch32(NotEqual, regT0, Imm32(JSValue::CellTag));
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
-    Jump valueIsNotObject = branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)); // FIXME: Maybe remove this test.
-
-    // Check proto is object.
-    loadPtr(Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
-    addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
+    addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance)));
 
     // Optimistically load the result true, and start looping.
     // Initially, regT1 still contains proto and regT2 still contains value.
 
     // Optimistically load the result true, and start looping.
     // Initially, regT1 still contains proto and regT2 still contains value.
@@ -554,16 +487,14 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
     move(Imm32(JSValue::TrueTag), regT0);
     Label loop(this);
 
     move(Imm32(JSValue::TrueTag), regT0);
     Label loop(this);
 
-    // Load the prototype of the object in regT2.  If this is equal to regT1 - WIN!
+    // Load the prototype of the cell in regT2.  If this is equal to regT1 - WIN!
     // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again.
     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
     load32(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
     Jump isInstance = branchPtr(Equal, regT2, regT1);
     // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again.
     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
     load32(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
     Jump isInstance = branchPtr(Equal, regT2, regT1);
-    branch32(NotEqual, regT2, Imm32(0), loop);
+    branchTest32(NonZero, regT2).linkTo(loop, this);
 
     // We get here either by dropping out of the loop, or if value was not an Object.  Result is false.
 
     // We get here either by dropping out of the loop, or if value was not an Object.  Result is false.
-    valueIsImmediate.link(this);
-    valueIsNotObject.link(this);
     move(Imm32(JSValue::FalseTag), regT0);
 
     // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
     move(Imm32(JSValue::FalseTag), regT0);
 
     // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
@@ -578,11 +509,10 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas
     unsigned baseVal = currentInstruction[3].u.operand;
     unsigned proto = currentInstruction[4].u.operand;
 
     unsigned baseVal = currentInstruction[3].u.operand;
     unsigned proto = currentInstruction[4].u.operand;
 
+    linkSlowCaseIfNotJSCell(iter, value);
     linkSlowCaseIfNotJSCell(iter, baseVal);
     linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
     linkSlowCaseIfNotJSCell(iter, baseVal);
     linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
-    linkSlowCase(iter);
-    linkSlowCase(iter);
 
     JITStubCall stubCall(this, cti_op_instanceof);
     stubCall.addArgument(value);
 
     JITStubCall stubCall(this, cti_op_instanceof);
     stubCall.addArgument(value);
@@ -594,7 +524,7 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas
 void JIT::emit_op_new_func(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_func);
 void JIT::emit_op_new_func(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_func);
-    stubCall.addArgument(ImmPtr(m_codeBlock->function(currentInstruction[2].u.operand)));
+    stubCall.addArgument(ImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -727,40 +657,6 @@ void JIT::emit_op_strcat(Instruction* currentInstruction)
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
-void JIT::emit_op_loop_if_true(Instruction* currentInstruction)
-{
-    unsigned cond = currentInstruction[1].u.operand;
-    unsigned target = currentInstruction[2].u.operand;
-
-    emitTimeoutCheck();
-
-    emitLoad(cond, regT1, regT0);
-
-    Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
-    addJump(branch32(NotEqual, regT0, Imm32(0)), target + 2);
-    Jump isNotZero = jump();
-
-    isNotInteger.link(this);
-
-    addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target + 2);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::FalseTag)));
-
-    isNotZero.link(this);
-}
-
-void JIT::emitSlow_op_loop_if_true(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned cond = currentInstruction[1].u.operand;
-    unsigned target = currentInstruction[2].u.operand;
-
-    linkSlowCase(iter);
-
-    JITStubCall stubCall(this, cti_op_jtrue);
-    stubCall.addArgument(cond);
-    stubCall.call();
-    emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 2);
-}
-
 void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_base);
 void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_base);
@@ -851,11 +747,11 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction)
     emitLoad(cond, regT1, regT0);
 
     Jump isTrue = branch32(Equal, regT1, Imm32(JSValue::TrueTag));
     emitLoad(cond, regT1, regT0);
 
     Jump isTrue = branch32(Equal, regT1, Imm32(JSValue::TrueTag));
-    addJump(branch32(Equal, regT1, Imm32(JSValue::FalseTag)), target + 2);
+    addJump(branch32(Equal, regT1, Imm32(JSValue::FalseTag)), target);
 
     Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
     Jump isTrue2 = branch32(NotEqual, regT0, Imm32(0));
 
     Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
     Jump isTrue2 = branch32(NotEqual, regT0, Imm32(0));
-    addJump(jump(), target + 2);
+    addJump(jump(), target);
 
     if (supportsFloatingPoint()) {
         isNotInteger.link(this);
 
     if (supportsFloatingPoint()) {
         isNotInteger.link(this);
@@ -864,7 +760,7 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction)
 
         zeroDouble(fpRegT0);
         emitLoadDouble(cond, fpRegT1);
 
         zeroDouble(fpRegT0);
         emitLoadDouble(cond, fpRegT1);
-        addJump(branchDouble(DoubleEqual, fpRegT0, fpRegT1), target + 2);
+        addJump(branchDouble(DoubleEqualOrUnordered, fpRegT0, fpRegT1), target);
     } else
         addSlowCase(isNotInteger);
 
     } else
         addSlowCase(isNotInteger);
 
@@ -881,7 +777,7 @@ void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEnt
     JITStubCall stubCall(this, cti_op_jtrue);
     stubCall.addArgument(cond);
     stubCall.call();
     JITStubCall stubCall(this, cti_op_jtrue);
     stubCall.addArgument(cond);
     stubCall.call();
-    emitJumpSlowToHot(branchTest32(Zero, regT0), target + 2); // Inverted.
+    emitJumpSlowToHot(branchTest32(Zero, regT0), target); // Inverted.
 }
 
 void JIT::emit_op_jtrue(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_jtrue(Instruction* currentInstruction)
@@ -892,11 +788,11 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction)
     emitLoad(cond, regT1, regT0);
 
     Jump isFalse = branch32(Equal, regT1, Imm32(JSValue::FalseTag));
     emitLoad(cond, regT1, regT0);
 
     Jump isFalse = branch32(Equal, regT1, Imm32(JSValue::FalseTag));
-    addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target + 2);
+    addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target);
 
     Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
     Jump isFalse2 = branch32(Equal, regT0, Imm32(0));
 
     Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
     Jump isFalse2 = branch32(Equal, regT0, Imm32(0));
-    addJump(jump(), target + 2);
+    addJump(jump(), target);
 
     if (supportsFloatingPoint()) {
         isNotInteger.link(this);
 
     if (supportsFloatingPoint()) {
         isNotInteger.link(this);
@@ -905,7 +801,7 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction)
 
         zeroDouble(fpRegT0);
         emitLoadDouble(cond, fpRegT1);
 
         zeroDouble(fpRegT0);
         emitLoadDouble(cond, fpRegT1);
-        addJump(branchDouble(DoubleNotEqual, fpRegT0, fpRegT1), target + 2);
+        addJump(branchDouble(DoubleNotEqual, fpRegT0, fpRegT1), target);
     } else
         addSlowCase(isNotInteger);
 
     } else
         addSlowCase(isNotInteger);
 
@@ -922,7 +818,7 @@ void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntr
     JITStubCall stubCall(this, cti_op_jtrue);
     stubCall.addArgument(cond);
     stubCall.call();
     JITStubCall stubCall(this, cti_op_jtrue);
     stubCall.addArgument(cond);
     stubCall.call();
-    emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 2);
+    emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
 }
 
 void JIT::emit_op_jeq_null(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_jeq_null(Instruction* currentInstruction)
@@ -936,7 +832,7 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction)
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);
+    addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
 
     Jump wasNotImmediate = jump();
 
 
     Jump wasNotImmediate = jump();
 
@@ -947,7 +843,7 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction)
     set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
     or32(regT2, regT1);
 
     set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
     or32(regT2, regT1);
 
-    addJump(branchTest32(NonZero, regT1), target + 2);
+    addJump(branchTest32(NonZero, regT1), target);
 
     wasNotImmediate.link(this);
 }
 
     wasNotImmediate.link(this);
 }
@@ -963,7 +859,7 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction)
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);
+    addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
 
     Jump wasNotImmediate = jump();
 
 
     Jump wasNotImmediate = jump();
 
@@ -974,7 +870,7 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction)
     set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
     or32(regT2, regT1);
 
     set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
     or32(regT2, regT1);
 
-    addJump(branchTest32(Zero, regT1), target + 2);
+    addJump(branchTest32(Zero, regT1), target);
 
     wasNotImmediate.link(this);
 }
 
     wasNotImmediate.link(this);
 }
@@ -986,8 +882,8 @@ void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
     unsigned target = currentInstruction[3].u.operand;
 
     emitLoad(src, regT1, regT0);
     unsigned target = currentInstruction[3].u.operand;
 
     emitLoad(src, regT1, regT0);
-    addJump(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)), target + 3);
-    addJump(branchPtr(NotEqual, regT0, ImmPtr(ptr)), target + 3);
+    addJump(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)), target);
+    addJump(branchPtr(NotEqual, regT0, ImmPtr(ptr)), target);
 }
 
 void JIT::emit_op_jsr(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_jsr(Instruction* currentInstruction)
@@ -995,7 +891,7 @@ void JIT::emit_op_jsr(Instruction* currentInstruction)
     int retAddrDst = currentInstruction[1].u.operand;
     int target = currentInstruction[2].u.operand;
     DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
     int retAddrDst = currentInstruction[1].u.operand;
     int target = currentInstruction[2].u.operand;
     DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
-    addJump(jump(), target + 2);
+    addJump(jump(), target);
     m_jsrSites.append(JSRInfo(storeLocation, label()));
 }
 
     m_jsrSites.append(JSRInfo(storeLocation, label()));
 }
 
@@ -1236,7 +1132,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_func_exp);
 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_func_exp);
-    stubCall.addArgument(ImmPtr(m_codeBlock->functionExpression(currentInstruction[2].u.operand)));
+    stubCall.addArgument(ImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -1261,23 +1157,109 @@ void JIT::emit_op_throw(Instruction* currentInstruction)
 #endif
 }
 
 #endif
 }
 
+void JIT::emit_op_get_pnames(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int i = currentInstruction[3].u.operand;
+    int size = currentInstruction[4].u.operand;
+    int breakTarget = currentInstruction[5].u.operand;
+
+    JumpList isNotObject;
+
+    emitLoad(base, regT1, regT0);
+    if (!m_codeBlock->isKnownNotImmediate(base))
+        isNotObject.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+    if (base != m_codeBlock->thisRegister()) {
+        loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+        isNotObject.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
+    }
+
+    // We could inline the case where you have a valid cache, but
+    // this call doesn't seem to be hot.
+    Label isObject(this);
+    JITStubCall getPnamesStubCall(this, cti_op_get_pnames);
+    getPnamesStubCall.addArgument(regT0);
+    getPnamesStubCall.call(dst);
+    load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3);
+    store32(Imm32(0), addressFor(i));
+    store32(regT3, addressFor(size));
+    Jump end = jump();
+
+    isNotObject.link(this);
+    addJump(branch32(Equal, regT1, Imm32(JSValue::NullTag)), breakTarget);
+    addJump(branch32(Equal, regT1, Imm32(JSValue::UndefinedTag)), breakTarget);
+    JITStubCall toObjectStubCall(this, cti_to_object);
+    toObjectStubCall.addArgument(regT1, regT0);
+    toObjectStubCall.call(base);
+    jump().linkTo(isObject, this);
+    
+    end.link(this);
+}
+
 void JIT::emit_op_next_pname(Instruction* currentInstruction)
 {
     int dst = currentInstruction[1].u.operand;
 void JIT::emit_op_next_pname(Instruction* currentInstruction)
 {
     int dst = currentInstruction[1].u.operand;
-    int iter = currentInstruction[2].u.operand;
-    int target = currentInstruction[3].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int i = currentInstruction[3].u.operand;
+    int size = currentInstruction[4].u.operand;
+    int it = currentInstruction[5].u.operand;
+    int target = currentInstruction[6].u.operand;
+    
+    JumpList callHasProperty;
+
+    Label begin(this);
+    load32(addressFor(i), regT0);
+    Jump end = branch32(Equal, regT0, addressFor(size));
+
+    // Grab key @ i
+    loadPtr(addressFor(it), regT1);
+    loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2);
+    load32(BaseIndex(regT2, regT0, TimesEight), regT2);
+    store32(Imm32(JSValue::CellTag), tagFor(dst));
+    store32(regT2, payloadFor(dst));
+
+    // Increment i
+    add32(Imm32(1), regT0);
+    store32(regT0, addressFor(i));
+
+    // Verify that i is valid:
+    loadPtr(addressFor(base), regT0);
 
 
-    load32(Address(callFrameRegister, (iter * sizeof(Register))), regT0);
+    // Test base's structure
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+    callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))));
+
+    // Test base's prototype chain
+    loadPtr(Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedPrototypeChain))), regT3);
+    loadPtr(Address(regT3, OBJECT_OFFSETOF(StructureChain, m_vector)), regT3);
+    addJump(branchTestPtr(Zero, Address(regT3)), target);
+
+    Label checkPrototype(this);
+    callHasProperty.append(branch32(Equal, Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), Imm32(JSValue::NullTag)));
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+    callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3)));
+    addPtr(Imm32(sizeof(Structure*)), regT3);
+    branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this);
+
+    // Continue loop.
+    addJump(jump(), target);
 
 
-    JITStubCall stubCall(this, cti_op_next_pname);
+    // Slow case: Ask the object if i is valid.
+    callHasProperty.link(this);
+    loadPtr(addressFor(dst), regT1);
+    JITStubCall stubCall(this, cti_has_property);
     stubCall.addArgument(regT0);
     stubCall.addArgument(regT0);
+    stubCall.addArgument(regT1);
     stubCall.call();
 
     stubCall.call();
 
-    Jump endOfIter = branchTestPtr(Zero, regT0);
-    emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_next_pname), dst, regT1, regT0);
-    addJump(jump(), target + 3);
-    endOfIter.link(this);
+    // Test for valid key.
+    addJump(branchTest32(NonZero, regT0), target);
+    jump().linkTo(begin, this);
+
+    // End of loop.
+    end.link(this);
 }
 
 void JIT::emit_op_push_scope(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_push_scope(Instruction* currentInstruction)
@@ -1300,7 +1282,7 @@ void JIT::emit_op_to_jsnumber(Instruction* currentInstruction)
     emitLoad(src, regT1, regT0);
 
     Jump isInt32 = branch32(Equal, regT1, Imm32(JSValue::Int32Tag));
     emitLoad(src, regT1, regT0);
 
     Jump isInt32 = branch32(Equal, regT1, Imm32(JSValue::Int32Tag));
-    addSlowCase(branch32(AboveOrEqual, regT1, Imm32(JSValue::DeletedValueTag)));
+    addSlowCase(branch32(AboveOrEqual, regT1, Imm32(JSValue::EmptyValueTag)));
     isInt32.link(this);
 
     if (src != dst)
     isInt32.link(this);
 
     if (src != dst)
@@ -1347,7 +1329,7 @@ void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
     JITStubCall stubCall(this, cti_op_jmp_scopes);
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
     stubCall.call();
     JITStubCall stubCall(this, cti_op_jmp_scopes);
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
     stubCall.call();
-    addJump(jump(), currentInstruction[2].u.operand + 2);
+    addJump(jump(), currentInstruction[2].u.operand);
 }
 
 void JIT::emit_op_switch_imm(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_switch_imm(Instruction* currentInstruction)
@@ -1444,8 +1426,7 @@ void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
 
 void JIT::emit_op_create_arguments(Instruction*)
 {
 
 void JIT::emit_op_create_arguments(Instruction*)
 {
-    Jump argsNotCell = branch32(NotEqual, tagFor(RegisterFile::ArgumentsRegister, callFrameRegister), Imm32(JSValue::CellTag));
-    Jump argsNotNull = branchTestPtr(NonZero, payloadFor(RegisterFile::ArgumentsRegister, callFrameRegister));
+    Jump argsCreated = branch32(NotEqual, tagFor(RegisterFile::ArgumentsRegister, callFrameRegister), Imm32(JSValue::EmptyValueTag));
 
     // If we get here the arguments pointer is a null cell - i.e. arguments need lazy creation.
     if (m_codeBlock->m_numParameters == 1)
 
     // If we get here the arguments pointer is a null cell - i.e. arguments need lazy creation.
     if (m_codeBlock->m_numParameters == 1)
@@ -1453,8 +1434,7 @@ void JIT::emit_op_create_arguments(Instruction*)
     else
         JITStubCall(this, cti_op_create_arguments).call();
 
     else
         JITStubCall(this, cti_op_create_arguments).call();
 
-    argsNotCell.link(this);
-    argsNotNull.link(this);
+    argsCreated.link(this);
 }
     
 void JIT::emit_op_init_arguments(Instruction*)
 }
     
 void JIT::emit_op_init_arguments(Instruction*)
@@ -1515,7 +1495,7 @@ void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
 #define RECORD_JUMP_TARGET(targetOffset) \
    do { m_labels[m_bytecodeIndex + (targetOffset)].used(); } while (false)
 
 #define RECORD_JUMP_TARGET(targetOffset) \
    do { m_labels[m_bytecodeIndex + (targetOffset)].used(); } while (false)
 
-void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallPreLink, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
+void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
 {
 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
     // (2) The second function provides fast property access for string length
 {
 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
     // (2) The second function provides fast property access for string length
@@ -1526,8 +1506,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
 
     // Checks out okay! - get the length from the Ustring.
     Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
 
     // Checks out okay! - get the length from the Ustring.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSString, m_value) + OBJECT_OFFSETOF(UString, m_rep)), regT0);
-    load32(Address(regT0, OBJECT_OFFSETOF(UString::Rep, len)), regT0);
+    load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_stringLength)), regT0);
 
     Jump string_failureCases3 = branch32(Above, regT0, Imm32(JSImmediate::maxImmediateInt));
 
 
     Jump string_failureCases3 = branch32(Above, regT0, Imm32(JSImmediate::maxImmediateInt));
 
@@ -1540,126 +1519,77 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
     COMPILE_ASSERT(sizeof(CodeType) == 4, CodeTypeEnumMustBe32Bit);
 
     // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
     COMPILE_ASSERT(sizeof(CodeType) == 4, CodeTypeEnumMustBe32Bit);
 
-    Label virtualCallPreLinkBegin = align();
-
-    // Load the callee CodeBlock* into eax
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_body)), regT3);
-    loadPtr(Address(regT3, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT0);
-    Jump hasCodeBlock1 = branchTestPtr(NonZero, regT0);
-    preserveReturnAddressAfterCall(regT3);
-    restoreArgumentReference();
-    Call callJSFunction1 = call();
-    emitGetJITStubArg(1, regT2);
-    emitGetJITStubArg(3, regT1);
-    restoreReturnAddressBeforeReturn(regT3);
-    hasCodeBlock1.link(this);
-
-    Jump isNativeFunc1 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
-
-    // Check argCount matches callee arity.
-    Jump arityCheckOkay1 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
-    preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 2);
-    emitPutJITStubArg(regT0, 4);
-    restoreArgumentReference();
-    Call callArityCheck1 = call();
-    move(regT1, callFrameRegister);
-    emitGetJITStubArg(1, regT2);
-    emitGetJITStubArg(3, regT1);
-    restoreReturnAddressBeforeReturn(regT3);
-    arityCheckOkay1.link(this);
-    isNativeFunc1.link(this);
-    
-    compileOpCallInitializeCallFrame();
-
-    preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 2);
-    restoreArgumentReference();
-    Call callDontLazyLinkCall = call();
-    emitGetJITStubArg(1, regT2);
-    restoreReturnAddressBeforeReturn(regT3);
-
-    jump(regT0);
-
+    // VirtualCallLink Trampoline
+    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
     Label virtualCallLinkBegin = align();
     Label virtualCallLinkBegin = align();
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
 
 
-    // Load the callee CodeBlock* into eax
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_body)), regT3);
-    loadPtr(Address(regT3, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT0);
-    Jump hasCodeBlock2 = branchTestPtr(NonZero, regT0);
+    Jump isNativeFunc2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
+
+    Jump hasCodeBlock2 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
     preserveReturnAddressAfterCall(regT3);
     restoreArgumentReference();
     Call callJSFunction2 = call();
     preserveReturnAddressAfterCall(regT3);
     restoreArgumentReference();
     Call callJSFunction2 = call();
-    emitGetJITStubArg(1, regT2);
-    emitGetJITStubArg(3, regT1);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    emitGetJITStubArg(2, regT1); // argCount
     restoreReturnAddressBeforeReturn(regT3);
     hasCodeBlock2.link(this);
 
     restoreReturnAddressBeforeReturn(regT3);
     hasCodeBlock2.link(this);
 
-    Jump isNativeFunc2 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
-
     // Check argCount matches callee arity.
     // Check argCount matches callee arity.
-    Jump arityCheckOkay2 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
+    Jump arityCheckOkay2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
     preserveReturnAddressAfterCall(regT3);
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 2);
-    emitPutJITStubArg(regT0, 4);
+    emitPutJITStubArg(regT3, 1); // return address
     restoreArgumentReference();
     Call callArityCheck2 = call();
     move(regT1, callFrameRegister);
     restoreArgumentReference();
     Call callArityCheck2 = call();
     move(regT1, callFrameRegister);
-    emitGetJITStubArg(1, regT2);
-    emitGetJITStubArg(3, regT1);
+    emitGetJITStubArg(2, regT1); // argCount
     restoreReturnAddressBeforeReturn(regT3);
     arityCheckOkay2.link(this);
     restoreReturnAddressBeforeReturn(regT3);
     arityCheckOkay2.link(this);
+
     isNativeFunc2.link(this);
 
     compileOpCallInitializeCallFrame();
     isNativeFunc2.link(this);
 
     compileOpCallInitializeCallFrame();
-
     preserveReturnAddressAfterCall(regT3);
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 2);
+    emitPutJITStubArg(regT3, 1); // return address
     restoreArgumentReference();
     Call callLazyLinkCall = call();
     restoreReturnAddressBeforeReturn(regT3);
     restoreArgumentReference();
     Call callLazyLinkCall = call();
     restoreReturnAddressBeforeReturn(regT3);
-
     jump(regT0);
 
     jump(regT0);
 
+    // VirtualCall Trampoline
+    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
     Label virtualCallBegin = align();
     Label virtualCallBegin = align();
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
 
 
-    // Load the callee CodeBlock* into eax
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_body)), regT3);
-    loadPtr(Address(regT3, OBJECT_OFFSETOF(FunctionBodyNode, m_code)), regT0);
-    Jump hasCodeBlock3 = branchTestPtr(NonZero, regT0);
+    Jump isNativeFunc3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
+
+    Jump hasCodeBlock3 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
     preserveReturnAddressAfterCall(regT3);
     restoreArgumentReference();
     preserveReturnAddressAfterCall(regT3);
     restoreArgumentReference();
-    Call callJSFunction3 = call();
-    emitGetJITStubArg(1, regT2);
-    emitGetJITStubArg(3, regT1);
+    Call callJSFunction1 = call();
+    emitGetJITStubArg(2, regT1); // argCount
     restoreReturnAddressBeforeReturn(regT3);
     restoreReturnAddressBeforeReturn(regT3);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_body)), regT3); // reload the function body nody, so we can reload the code pointer.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
     hasCodeBlock3.link(this);
     
     hasCodeBlock3.link(this);
     
-    Jump isNativeFunc3 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_codeType)), Imm32(NativeCode));
-
     // Check argCount matches callee arity.
     // Check argCount matches callee arity.
-    Jump arityCheckOkay3 = branch32(Equal, Address(regT0, OBJECT_OFFSETOF(CodeBlock, m_numParameters)), regT1);
+    Jump arityCheckOkay3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
     preserveReturnAddressAfterCall(regT3);
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 2);
-    emitPutJITStubArg(regT0, 4);
+    emitPutJITStubArg(regT3, 1); // return address
     restoreArgumentReference();
     restoreArgumentReference();
-    Call callArityCheck3 = call();
+    Call callArityCheck1 = call();
     move(regT1, callFrameRegister);
     move(regT1, callFrameRegister);
-    emitGetJITStubArg(1, regT2);
-    emitGetJITStubArg(3, regT1);
+    emitGetJITStubArg(2, regT1); // argCount
     restoreReturnAddressBeforeReturn(regT3);
     restoreReturnAddressBeforeReturn(regT3);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_body)), regT3); // reload the function body nody, so we can reload the code pointer.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
     arityCheckOkay3.link(this);
     arityCheckOkay3.link(this);
+
     isNativeFunc3.link(this);
 
     isNativeFunc3.link(this);
 
-    // load ctiCode from the new codeBlock.
-    loadPtr(Address(regT3, OBJECT_OFFSETOF(FunctionBodyNode, m_jitCode)), regT0);
-    
     compileOpCallInitializeCallFrame();
     compileOpCallInitializeCallFrame();
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCode)), regT0);
     jump(regT0);
 
     jump(regT0);
 
-    
     Label nativeCallThunk = align();
     preserveReturnAddressAfterCall(regT0);
     emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address
     Label nativeCallThunk = align();
     preserveReturnAddressAfterCall(regT0);
     emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address
@@ -1671,43 +1601,43 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
     
 
     emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
     
 
-#if PLATFORM(X86_64)
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, X86::ecx);
+#if CPU(X86_64)
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, X86Registers::ecx);
 
     // Allocate stack space for our arglist
     subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
     COMPILE_ASSERT((sizeof(ArgList) & 0xf) == 0, ArgList_should_by_16byte_aligned);
     
     // Set up arguments
 
     // Allocate stack space for our arglist
     subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
     COMPILE_ASSERT((sizeof(ArgList) & 0xf) == 0, ArgList_should_by_16byte_aligned);
     
     // Set up arguments
-    subPtr(Imm32(1), X86::ecx); // Don't include 'this' in argcount
+    subPtr(Imm32(1), X86Registers::ecx); // Don't include 'this' in argcount
 
     // Push argcount
 
     // Push argcount
-    storePtr(X86::ecx, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
+    storePtr(X86Registers::ecx, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
 
     // Calculate the start of the callframe header, and store in edx
 
     // Calculate the start of the callframe header, and store in edx
-    addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), callFrameRegister, X86::edx);
+    addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), callFrameRegister, X86Registers::edx);
     
     // Calculate start of arguments as callframe header - sizeof(Register) * argcount (ecx)
     
     // Calculate start of arguments as callframe header - sizeof(Register) * argcount (ecx)
-    mul32(Imm32(sizeof(Register)), X86::ecx, X86::ecx);
-    subPtr(X86::ecx, X86::edx);
+    mul32(Imm32(sizeof(Register)), X86Registers::ecx, X86Registers::ecx);
+    subPtr(X86Registers::ecx, X86Registers::edx);
 
     // push pointer to arguments
 
     // push pointer to arguments
-    storePtr(X86::edx, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
+    storePtr(X86Registers::edx, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
     
     // ArgList is passed by reference so is stackPointerRegister
     
     // ArgList is passed by reference so is stackPointerRegister
-    move(stackPointerRegister, X86::ecx);
+    move(stackPointerRegister, X86Registers::ecx);
     
     // edx currently points to the first argument, edx-sizeof(Register) points to 'this'
     
     // edx currently points to the first argument, edx-sizeof(Register) points to 'this'
-    loadPtr(Address(X86::edx, -(int32_t)sizeof(Register)), X86::edx);
+    loadPtr(Address(X86Registers::edx, -(int32_t)sizeof(Register)), X86Registers::edx);
     
     
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86::esi);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::esi);
 
 
-    move(callFrameRegister, X86::edi); 
+    move(callFrameRegister, X86Registers::edi); 
 
 
-    call(Address(X86::esi, OBJECT_OFFSETOF(JSFunction, m_data)));
+    call(Address(X86Registers::esi, OBJECT_OFFSETOF(JSFunction, m_data)));
     
     addPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
     
     addPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
-#elif PLATFORM(X86)
+#elif CPU(X86)
     emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
 
     /* We have two structs that we use to describe the stackframe we set up for our
     emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
 
     /* We have two structs that we use to describe the stackframe we set up for our
@@ -1718,7 +1648,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
      * not the rest of the callframe so we need a nice way to ensure we increment the
      * stack pointer by the right amount after the call.
      */
      * not the rest of the callframe so we need a nice way to ensure we increment the
      * stack pointer by the right amount after the call.
      */
-#if COMPILER(MSVC) || PLATFORM(LINUX)
+#if COMPILER(MSVC) || OS(LINUX)
     struct NativeCallFrameStructure {
       //  CallFrame* callFrame; // passed in EDX
         JSObject* callee;
     struct NativeCallFrameStructure {
       //  CallFrame* callFrame; // passed in EDX
         JSObject* callee;
@@ -1771,34 +1701,74 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     loadPtr(Address(regT1, -(int)sizeof(Register)), regT1);
     storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue)));
 
     loadPtr(Address(regT1, -(int)sizeof(Register)), regT1);
     storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue)));
 
-#if COMPILER(MSVC) || PLATFORM(LINUX)
+#if COMPILER(MSVC) || OS(LINUX)
     // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
     // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
-    addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86::ecx);
+    addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86Registers::ecx);
 
     // Plant callee
 
     // Plant callee
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86::eax);
-    storePtr(X86::eax, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, callee)));
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::eax);
+    storePtr(X86Registers::eax, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, callee)));
 
     // Plant callframe
 
     // Plant callframe
-    move(callFrameRegister, X86::edx);
+    move(callFrameRegister, X86Registers::edx);
 
 
-    call(Address(X86::eax, OBJECT_OFFSETOF(JSFunction, m_data)));
+    call(Address(X86Registers::eax, OBJECT_OFFSETOF(JSFunction, m_data)));
 
     // JSValue is a non-POD type
 
     // JSValue is a non-POD type
-    loadPtr(Address(X86::eax), X86::eax);
+    loadPtr(Address(X86Registers::eax), X86Registers::eax);
 #else
     // Plant callee
 #else
     // Plant callee
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86::edx);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::edx);
 
     // Plant callframe
 
     // Plant callframe
-    move(callFrameRegister, X86::ecx);
-    call(Address(X86::edx, OBJECT_OFFSETOF(JSFunction, m_data)));
+    move(callFrameRegister, X86Registers::ecx);
+    call(Address(X86Registers::edx, OBJECT_OFFSETOF(JSFunction, m_data)));
 #endif
 
     // We've put a few temporaries on the stack in addition to the actual arguments
     // so pull them off now
     addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister);
 
 #endif
 
     // We've put a few temporaries on the stack in addition to the actual arguments
     // so pull them off now
     addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister);
 
+#elif CPU(ARM)
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+
+    // Allocate stack space for our arglist
+    COMPILE_ASSERT((sizeof(ArgList) & 0x7) == 0, ArgList_should_by_8byte_aligned);
+    subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
+
+    // Set up arguments
+    subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
+
+    // Push argcount
+    storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
+
+    // Calculate the start of the callframe header, and store in regT1
+    move(callFrameRegister, regT1);
+    sub32(Imm32(RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), regT1);
+
+    // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT1)
+    mul32(Imm32(sizeof(Register)), regT0, regT0);
+    subPtr(regT0, regT1);
+
+    // push pointer to arguments
+    storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
+
+    // Setup arg3: regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this'
+    loadPtr(Address(regT1, -(int32_t)sizeof(Register)), regT2);
+
+    // Setup arg2:
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT1);
+
+    // Setup arg1:
+    move(callFrameRegister, regT0);
+
+    // Setup arg4: This is a plain hack
+    move(stackPointerRegister, ARMRegisters::r3);
+
+    call(Address(regT1, OBJECT_OFFSETOF(JSFunction, m_data)));
+
+    addPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
+
 #elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
 #error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
 #else
 #elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
 #error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
 #else
@@ -1825,7 +1795,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
     move(ImmPtr(&globalData->exceptionLocation), regT2);
     storePtr(regT1, regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
     move(ImmPtr(&globalData->exceptionLocation), regT2);
     storePtr(regT1, regT2);
-    move(ImmPtr(reinterpret_cast<void*>(ctiVMThrowTrampoline)), regT2);
+    move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
     restoreReturnAddressBeforeReturn(regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
     restoreReturnAddressBeforeReturn(regT2);
@@ -1847,18 +1817,16 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
 #endif
     patchBuffer.link(callArityCheck1, FunctionPtr(cti_op_call_arityCheck));
     patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
 #endif
     patchBuffer.link(callArityCheck1, FunctionPtr(cti_op_call_arityCheck));
-    patchBuffer.link(callArityCheck2, FunctionPtr(cti_op_call_arityCheck));
-    patchBuffer.link(callArityCheck3, FunctionPtr(cti_op_call_arityCheck));
     patchBuffer.link(callJSFunction1, FunctionPtr(cti_op_call_JSFunction));
     patchBuffer.link(callJSFunction1, FunctionPtr(cti_op_call_JSFunction));
+#if ENABLE(JIT_OPTIMIZE_CALL)
+    patchBuffer.link(callArityCheck2, FunctionPtr(cti_op_call_arityCheck));
     patchBuffer.link(callJSFunction2, FunctionPtr(cti_op_call_JSFunction));
     patchBuffer.link(callJSFunction2, FunctionPtr(cti_op_call_JSFunction));
-    patchBuffer.link(callJSFunction3, FunctionPtr(cti_op_call_JSFunction));
-    patchBuffer.link(callDontLazyLinkCall, FunctionPtr(cti_vm_dontLazyLinkCall));
     patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
     patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
+#endif
 
     CodeRef finalCode = patchBuffer.finalizeCode();
     *executablePool = finalCode.m_executablePool;
 
 
     CodeRef finalCode = patchBuffer.finalizeCode();
     *executablePool = finalCode.m_executablePool;
 
-    *ctiVirtualCallPreLink = trampolineAt(finalCode, virtualCallPreLinkBegin);
     *ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
     *ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
     *ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk);
     *ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
     *ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
     *ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk);
@@ -1903,49 +1871,8 @@ void JIT::emit_op_end(Instruction* currentInstruction)
 void JIT::emit_op_jmp(Instruction* currentInstruction)
 {
     unsigned target = currentInstruction[1].u.operand;
 void JIT::emit_op_jmp(Instruction* currentInstruction)
 {
     unsigned target = currentInstruction[1].u.operand;
-    addJump(jump(), target + 1);
-    RECORD_JUMP_TARGET(target + 1);
-}
-
-void JIT::emit_op_loop(Instruction* currentInstruction)
-{
-    emitTimeoutCheck();
-
-    unsigned target = currentInstruction[1].u.operand;
-    addJump(jump(), target + 1);
-}
-
-void JIT::emit_op_loop_if_less(Instruction* currentInstruction)
-{
-    emitTimeoutCheck();
-
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-    if (isOperandConstantImmediateInt(op2)) {
-        emitGetVirtualRegister(op1, regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
-        int32_t op2imm = getConstantOperandImmediateInt(op2);
-#else
-        int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
-#endif
-        addJump(branch32(LessThan, regT0, Imm32(op2imm)), target + 3);
-    } else if (isOperandConstantImmediateInt(op1)) {
-        emitGetVirtualRegister(op2, regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
-        int32_t op1imm = getConstantOperandImmediateInt(op1);
-#else
-        int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
-#endif
-        addJump(branch32(GreaterThan, regT0, Imm32(op1imm)), target + 3);
-    } else {
-        emitGetVirtualRegisters(op1, regT0, op2, regT1);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT1);
-        addJump(branch32(LessThan, regT0, regT1), target + 3);
-    }
+    addJump(jump(), target);
+    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
@@ -1963,12 +1890,12 @@ void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
 #else
         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
 #endif
 #else
         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
 #endif
-        addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target + 3);
+        addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target);
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
-        addJump(branch32(LessThanOrEqual, regT0, regT1), target + 3);
+        addJump(branch32(LessThanOrEqual, regT0, regT1), target);
     }
 }
 
     }
 }
 
@@ -1979,30 +1906,26 @@ void JIT::emit_op_new_object(Instruction* currentInstruction)
 
 void JIT::emit_op_instanceof(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_instanceof(Instruction* currentInstruction)
 {
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned value = currentInstruction[2].u.operand;
+    unsigned baseVal = currentInstruction[3].u.operand;
+    unsigned proto = currentInstruction[4].u.operand;
+
     // Load the operands (baseVal, proto, and value respectively) into registers.
     // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result.
     // Load the operands (baseVal, proto, and value respectively) into registers.
     // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result.
-    emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
-    emitGetVirtualRegister(currentInstruction[4].u.operand, regT1);
-    emitGetVirtualRegister(currentInstruction[2].u.operand, regT2);
+    emitGetVirtualRegister(value, regT2);
+    emitGetVirtualRegister(baseVal, regT0);
+    emitGetVirtualRegister(proto, regT1);
 
     // Check that baseVal & proto are cells.
 
     // Check that baseVal & proto are cells.
-    emitJumpSlowCaseIfNotJSCell(regT0);
-    emitJumpSlowCaseIfNotJSCell(regT1);
+    emitJumpSlowCaseIfNotJSCell(regT2, value);
+    emitJumpSlowCaseIfNotJSCell(regT0, baseVal);
+    emitJumpSlowCaseIfNotJSCell(regT1, proto);
 
 
-    // Check that baseVal is an object, that it 'ImplementsHasInstance' but that it does not 'OverridesHasInstance'.
+    // Check that baseVal 'ImplementsDefaultHasInstance'.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
-    addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
     addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance)));
 
     addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance)));
 
-    // If value is not an Object, return false.
-    Jump valueIsImmediate = emitJumpIfNotJSCell(regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
-    Jump valueIsNotObject = branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType));
-
-    // Check proto is object.
-    loadPtr(Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
-    addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
-
     // Optimistically load the result true, and start looping.
     // Initially, regT1 still contains proto and regT2 still contains value.
     // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain.
     // Optimistically load the result true, and start looping.
     // Initially, regT1 still contains proto and regT2 still contains value.
     // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain.
@@ -2014,22 +1937,20 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
     loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
     Jump isInstance = branchPtr(Equal, regT2, regT1);
     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
     loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
     Jump isInstance = branchPtr(Equal, regT2, regT1);
-    branchPtr(NotEqual, regT2, ImmPtr(JSValue::encode(jsNull())), loop);
+    emitJumpIfJSCell(regT2).linkTo(loop, this);
 
     // We get here either by dropping out of the loop, or if value was not an Object.  Result is false.
 
     // We get here either by dropping out of the loop, or if value was not an Object.  Result is false.
-    valueIsImmediate.link(this);
-    valueIsNotObject.link(this);
     move(ImmPtr(JSValue::encode(jsBoolean(false))), regT0);
 
     // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
     isInstance.link(this);
     move(ImmPtr(JSValue::encode(jsBoolean(false))), regT0);
 
     // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
     isInstance.link(this);
-    emitPutVirtualRegister(currentInstruction[1].u.operand);
+    emitPutVirtualRegister(dst);
 }
 
 void JIT::emit_op_new_func(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_func);
 }
 
 void JIT::emit_op_new_func(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_func);
-    stubCall.addArgument(ImmPtr(m_codeBlock->function(currentInstruction[2].u.operand)));
+    stubCall.addArgument(ImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -2192,21 +2113,6 @@ void JIT::emit_op_strcat(Instruction* currentInstruction)
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
-void JIT::emit_op_loop_if_true(Instruction* currentInstruction)
-{
-    emitTimeoutCheck();
-
-    unsigned target = currentInstruction[2].u.operand;
-    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
-
-    Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0))));
-    addJump(emitJumpIfImmediateInteger(regT0), target + 2);
-
-    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target + 2);
-    addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))));
-
-    isZero.link(this);
-};
 void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_base);
 void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_base);
@@ -2269,14 +2175,14 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction)
     unsigned target = currentInstruction[2].u.operand;
     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
 
     unsigned target = currentInstruction[2].u.operand;
     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
 
-    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))), target + 2);
+    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))), target);
     Jump isNonZero = emitJumpIfImmediateInteger(regT0);
 
     Jump isNonZero = emitJumpIfImmediateInteger(regT0);
 
-    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))), target + 2);
+    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))), target);
     addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))));
 
     isNonZero.link(this);
     addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))));
 
     isNonZero.link(this);
-    RECORD_JUMP_TARGET(target + 2);
+    RECORD_JUMP_TARGET(target);
 };
 void JIT::emit_op_jeq_null(Instruction* currentInstruction)
 {
 };
 void JIT::emit_op_jeq_null(Instruction* currentInstruction)
 {
@@ -2288,16 +2194,16 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction)
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);
+    addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
     Jump wasNotImmediate = jump();
 
     // Now handle the immediate cases - undefined & null
     isImmediate.link(this);
     andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
     Jump wasNotImmediate = jump();
 
     // Now handle the immediate cases - undefined & null
     isImmediate.link(this);
     andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
-    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNull()))), target + 2);            
+    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNull()))), target);            
 
     wasNotImmediate.link(this);
 
     wasNotImmediate.link(this);
-    RECORD_JUMP_TARGET(target + 2);
+    RECORD_JUMP_TARGET(target);
 };
 void JIT::emit_op_jneq_null(Instruction* currentInstruction)
 {
 };
 void JIT::emit_op_jneq_null(Instruction* currentInstruction)
 {
@@ -2309,16 +2215,16 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction)
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);
+    addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
     Jump wasNotImmediate = jump();
 
     // Now handle the immediate cases - undefined & null
     isImmediate.link(this);
     andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
     Jump wasNotImmediate = jump();
 
     // Now handle the immediate cases - undefined & null
     isImmediate.link(this);
     andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
-    addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsNull()))), target + 2);            
+    addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsNull()))), target);            
 
     wasNotImmediate.link(this);
 
     wasNotImmediate.link(this);
-    RECORD_JUMP_TARGET(target + 2);
+    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
@@ -2328,9 +2234,9 @@ void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
     unsigned target = currentInstruction[3].u.operand;
     
     emitGetVirtualRegister(src, regT0);
     unsigned target = currentInstruction[3].u.operand;
     
     emitGetVirtualRegister(src, regT0);
-    addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue(ptr)))), target + 3);            
+    addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue(ptr)))), target);            
 
 
-    RECORD_JUMP_TARGET(target + 3);
+    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_jsr(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_jsr(Instruction* currentInstruction)
@@ -2338,10 +2244,10 @@ void JIT::emit_op_jsr(Instruction* currentInstruction)
     int retAddrDst = currentInstruction[1].u.operand;
     int target = currentInstruction[2].u.operand;
     DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
     int retAddrDst = currentInstruction[1].u.operand;
     int target = currentInstruction[2].u.operand;
     DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
-    addJump(jump(), target + 2);
+    addJump(jump(), target);
     m_jsrSites.append(JSRInfo(storeLocation, label()));
     killLastResultRegister();
     m_jsrSites.append(JSRInfo(storeLocation, label()));
     killLastResultRegister();
-    RECORD_JUMP_TARGET(target + 2);
+    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_sret(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_sret(Instruction* currentInstruction)
@@ -2383,7 +2289,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_func_exp);
 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_func_exp);
-    stubCall.addArgument(ImmPtr(m_codeBlock->functionExpression(currentInstruction[2].u.operand)));
+    stubCall.addArgument(ImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -2393,13 +2299,13 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction)
     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
 
     Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0))));
     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
 
     Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0))));
-    addJump(emitJumpIfImmediateInteger(regT0), target + 2);
+    addJump(emitJumpIfImmediateInteger(regT0), target);
 
 
-    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target + 2);
+    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target);
     addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))));
 
     isZero.link(this);
     addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))));
 
     isZero.link(this);
-    RECORD_JUMP_TARGET(target + 2);
+    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_neq(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_neq(Instruction* currentInstruction)
@@ -2450,15 +2356,116 @@ void JIT::emit_op_throw(Instruction* currentInstruction)
 #endif
 }
 
 #endif
 }
 
+void JIT::emit_op_get_pnames(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int i = currentInstruction[3].u.operand;
+    int size = currentInstruction[4].u.operand;
+    int breakTarget = currentInstruction[5].u.operand;
+
+    JumpList isNotObject;
+
+    emitGetVirtualRegister(base, regT0);
+    if (!m_codeBlock->isKnownNotImmediate(base))
+        isNotObject.append(emitJumpIfNotJSCell(regT0));
+    if (base != m_codeBlock->thisRegister()) {
+        loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+        isNotObject.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
+    }
+
+    // We could inline the case where you have a valid cache, but
+    // this call doesn't seem to be hot.
+    Label isObject(this);
+    JITStubCall getPnamesStubCall(this, cti_op_get_pnames);
+    getPnamesStubCall.addArgument(regT0);
+    getPnamesStubCall.call(dst);
+    load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3);
+    store32(Imm32(0), addressFor(i));
+    store32(regT3, addressFor(size));
+    Jump end = jump();
+
+    isNotObject.link(this);
+    move(regT0, regT1);
+    and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT1);
+    addJump(branch32(Equal, regT1, Imm32(JSImmediate::FullTagTypeNull)), breakTarget);
+
+    JITStubCall toObjectStubCall(this, cti_to_object);
+    toObjectStubCall.addArgument(regT0);
+    toObjectStubCall.call(base);
+    jump().linkTo(isObject, this);
+    
+    end.link(this);
+}
+
 void JIT::emit_op_next_pname(Instruction* currentInstruction)
 {
 void JIT::emit_op_next_pname(Instruction* currentInstruction)
 {
-    JITStubCall stubCall(this, cti_op_next_pname);
-    stubCall.addArgument(currentInstruction[2].u.operand, regT2);
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int i = currentInstruction[3].u.operand;
+    int size = currentInstruction[4].u.operand;
+    int it = currentInstruction[5].u.operand;
+    int target = currentInstruction[6].u.operand;
+    
+    JumpList callHasProperty;
+
+    Label begin(this);
+    load32(addressFor(i), regT0);
+    Jump end = branch32(Equal, regT0, addressFor(size));
+
+    // Grab key @ i
+    loadPtr(addressFor(it), regT1);
+    loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2);
+
+#if USE(JSVALUE64)
+    loadPtr(BaseIndex(regT2, regT0, TimesEight), regT2);
+#else
+    loadPtr(BaseIndex(regT2, regT0, TimesFour), regT2);
+#endif
+
+    emitPutVirtualRegister(dst, regT2);
+
+    // Increment i
+    add32(Imm32(1), regT0);
+    store32(regT0, addressFor(i));
+
+    // Verify that i is valid:
+    emitGetVirtualRegister(base, regT0);
+
+    // Test base's structure
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+    callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))));
+
+    // Test base's prototype chain
+    loadPtr(Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedPrototypeChain))), regT3);
+    loadPtr(Address(regT3, OBJECT_OFFSETOF(StructureChain, m_vector)), regT3);
+    addJump(branchTestPtr(Zero, Address(regT3)), target);
+
+    Label checkPrototype(this);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
+    callHasProperty.append(emitJumpIfNotJSCell(regT2));
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+    callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3)));
+    addPtr(Imm32(sizeof(Structure*)), regT3);
+    branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this);
+
+    // Continue loop.
+    addJump(jump(), target);
+
+    // Slow case: Ask the object if i is valid.
+    callHasProperty.link(this);
+    emitGetVirtualRegister(dst, regT1);
+    JITStubCall stubCall(this, cti_has_property);
+    stubCall.addArgument(regT0);
+    stubCall.addArgument(regT1);
     stubCall.call();
     stubCall.call();
-    Jump endOfIter = branchTestPtr(Zero, regT0);
-    emitPutVirtualRegister(currentInstruction[1].u.operand);
-    addJump(jump(), currentInstruction[3].u.operand + 3);
-    endOfIter.link(this);
+
+    // Test for valid key.
+    addJump(branchTest32(NonZero, regT0), target);
+    jump().linkTo(begin, this);
+
+    // End of loop.
+    end.link(this);
 }
 
 void JIT::emit_op_push_scope(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_push_scope(Instruction* currentInstruction)
@@ -2542,8 +2549,8 @@ void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
     JITStubCall stubCall(this, cti_op_jmp_scopes);
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
     stubCall.call();
     JITStubCall stubCall(this, cti_op_jmp_scopes);
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
     stubCall.call();
-    addJump(jump(), currentInstruction[2].u.operand + 2);
-    RECORD_JUMP_TARGET(currentInstruction[2].u.operand + 2);
+    addJump(jump(), currentInstruction[2].u.operand);
+    RECORD_JUMP_TARGET(currentInstruction[2].u.operand);
 }
 
 void JIT::emit_op_switch_imm(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_switch_imm(Instruction* currentInstruction)
@@ -2769,62 +2776,20 @@ void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowC
 
 void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 
 void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    // The slow void JIT::emitSlow_that handles accesses to arrays (below) may jump back up to here. 
-    Label beginGetByValSlow(this);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned base = currentInstruction[2].u.operand;
+    unsigned property = currentInstruction[3].u.operand;
 
 
-    Jump notImm = getSlowCase(iter);
-    linkSlowCase(iter);
-    linkSlowCase(iter);
-    emitFastArithIntToImmNoCheck(regT1, regT1);
+    linkSlowCase(iter); // property int32 check
+    linkSlowCaseIfNotJSCell(iter, base); // base cell check
+    linkSlowCase(iter); // base array check
+    linkSlowCase(iter); // vector length check
+    linkSlowCase(iter); // empty value
 
 
-    notImm.link(this);
     JITStubCall stubCall(this, cti_op_get_by_val);
     JITStubCall stubCall(this, cti_op_get_by_val);
-    stubCall.addArgument(regT0);
-    stubCall.addArgument(regT1);
-    stubCall.call(currentInstruction[1].u.operand);
-    emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
-
-    // This is slow void JIT::emitSlow_that handles accesses to arrays above the fast cut-off.
-    // First, check if this is an access to the vector
-    linkSlowCase(iter);
-    branch32(AboveOrEqual, regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_vectorLength)), beginGetByValSlow);
-
-    // okay, missed the fast region, but it is still in the vector.  Get the value.
-    loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT2);
-    // Check whether the value loaded is zero; if so we need to return undefined.
-    branchTestPtr(Zero, regT2, beginGetByValSlow);
-    move(regT2, regT0);
-    emitPutVirtualRegister(currentInstruction[1].u.operand, regT0);
-}
-
-void JIT::emitSlow_op_loop_if_less(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-    if (isOperandConstantImmediateInt(op2)) {
-        linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_loop_if_less);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(op2, regT2);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
-    } else if (isOperandConstantImmediateInt(op1)) {
-        linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_loop_if_less);
-        stubCall.addArgument(op1, regT2);
-        stubCall.addArgument(regT0);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
-    } else {
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_loop_if_less);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(regT1);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
-    }
+    stubCall.addArgument(base, regT2);
+    stubCall.addArgument(property, regT2);
+    stubCall.call(dst);
 }
 
 void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -2837,7 +2802,7 @@ void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<Slo
         stubCall.addArgument(regT0);
         stubCall.addArgument(currentInstruction[2].u.operand, regT2);
         stubCall.call();
         stubCall.addArgument(regT0);
         stubCall.addArgument(currentInstruction[2].u.operand, regT2);
         stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
     } else {
         linkSlowCase(iter);
         linkSlowCase(iter);
     } else {
         linkSlowCase(iter);
         linkSlowCase(iter);
@@ -2845,45 +2810,26 @@ void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<Slo
         stubCall.addArgument(regT0);
         stubCall.addArgument(regT1);
         stubCall.call();
         stubCall.addArgument(regT0);
         stubCall.addArgument(regT1);
         stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3);
+        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
     }
 }
 
 void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     }
 }
 
 void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    // Normal slow cases - either is not an immediate imm, or is an array.
-    Jump notImm = getSlowCase(iter);
-    linkSlowCase(iter);
-    linkSlowCase(iter);
-    emitFastArithIntToImmNoCheck(regT1, regT1);
+    unsigned base = currentInstruction[1].u.operand;
+    unsigned property = currentInstruction[2].u.operand;
+    unsigned value = currentInstruction[3].u.operand;
 
 
-    notImm.link(this); {
-        JITStubCall stubCall(this, cti_op_put_by_val);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(regT1);
-        stubCall.addArgument(currentInstruction[3].u.operand, regT2);
-        stubCall.call();
-        emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_put_by_val));
-    }
-
-    // slow cases for immediate int accesses to arrays
-    linkSlowCase(iter);
-    linkSlowCase(iter); {
-        JITStubCall stubCall(this, cti_op_put_by_val_array);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(regT1);
-        stubCall.addArgument(currentInstruction[3].u.operand, regT2);
-        stubCall.call();
-    }
-}
+    linkSlowCase(iter); // property int32 check
+    linkSlowCaseIfNotJSCell(iter, base); // base cell check
+    linkSlowCase(iter); // base not array check
+    linkSlowCase(iter); // in vector check
 
 
-void JIT::emitSlow_op_loop_if_true(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    linkSlowCase(iter);
-    JITStubCall stubCall(this, cti_op_jtrue);
-    stubCall.addArgument(regT0);
-    stubCall.call();
-    emitJumpSlowToHot(branchTest32(NonZero, regT0), currentInstruction[2].u.operand + 2);
+    JITStubCall stubPutByValCall(this, cti_op_put_by_val);
+    stubPutByValCall.addArgument(regT0);
+    stubPutByValCall.addArgument(property, regT2);
+    stubPutByValCall.addArgument(value, regT2);
+    stubPutByValCall.call();
 }
 
 void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -2901,7 +2847,7 @@ void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEnt
     JITStubCall stubCall(this, cti_op_jtrue);
     stubCall.addArgument(regT0);
     stubCall.call();
     JITStubCall stubCall(this, cti_op_jtrue);
     stubCall.addArgument(regT0);
     stubCall.call();
-    emitJumpSlowToHot(branchTest32(Zero, regT0), currentInstruction[2].u.operand + 2); // inverted!
+    emitJumpSlowToHot(branchTest32(Zero, regT0), currentInstruction[2].u.operand); // inverted!
 }
 
 void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -2918,7 +2864,7 @@ void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntr
     JITStubCall stubCall(this, cti_op_jtrue);
     stubCall.addArgument(regT0);
     stubCall.call();
     JITStubCall stubCall(this, cti_op_jtrue);
     stubCall.addArgument(regT0);
     stubCall.call();
-    emitJumpSlowToHot(branchTest32(NonZero, regT0), currentInstruction[2].u.operand + 2);
+    emitJumpSlowToHot(branchTest32(NonZero, regT0), currentInstruction[2].u.operand);
 }
 
 void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -2984,16 +2930,20 @@ void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCase
 
 void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 
 void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    linkSlowCase(iter);
-    linkSlowCase(iter);
-    linkSlowCase(iter);
-    linkSlowCase(iter);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned value = currentInstruction[2].u.operand;
+    unsigned baseVal = currentInstruction[3].u.operand;
+    unsigned proto = currentInstruction[4].u.operand;
+
+    linkSlowCaseIfNotJSCell(iter, value);
+    linkSlowCaseIfNotJSCell(iter, baseVal);
+    linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_instanceof);
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_instanceof);
-    stubCall.addArgument(currentInstruction[2].u.operand, regT2);
-    stubCall.addArgument(currentInstruction[3].u.operand, regT2);
-    stubCall.addArgument(currentInstruction[4].u.operand, regT2);
-    stubCall.call(currentInstruction[1].u.operand);
+    stubCall.addArgument(value, regT2);
+    stubCall.addArgument(baseVal, regT2);
+    stubCall.addArgument(proto, regT2);
+    stubCall.call(dst);
 }
 
 void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
index a6a28316e498c5a578c256be2467fa63a7720de6..ef95f996afb0a26421c56092eb10ffd502c112ea 100644 (file)
@@ -33,6 +33,7 @@
 #include "JITStubCall.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JITStubCall.h"
 #include "JSArray.h"
 #include "JSFunction.h"
+#include "JSPropertyNameIterator.h"
 #include "Interpreter.h"
 #include "LinkBuffer.h"
 #include "RepatchBuffer.h"
 #include "Interpreter.h"
 #include "LinkBuffer.h"
 #include "RepatchBuffer.h"
@@ -211,12 +212,17 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     emitLoad(base, regT1, regT0);
     emitJumpSlowCaseIfNotJSCell(base, regT1);
 
     emitLoad(base, regT1, regT0);
     emitJumpSlowCaseIfNotJSCell(base, regT1);
 
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
+
     Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT2);
     Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
 
     // This will be relinked to load the function without doing a load.
     DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0);
     Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT2);
     Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
 
     // This will be relinked to load the function without doing a load.
     DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0);
+    END_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
+    
     move(Imm32(JSValue::CellTag), regT1);
     Jump match = jump();
 
     move(Imm32(JSValue::CellTag), regT1);
     Jump match = jump();
 
@@ -273,11 +279,14 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
-    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_fastAccessCutoff))));
 
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT0);
-    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), regT1); // tag
-    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0); // payload
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3);
+    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength))));
+
+    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), regT1); // tag
+    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0); // payload
+    addSlowCase(branch32(Equal, regT1, Imm32(JSValue::EmptyValueTag)));
+
     emitStore(dst, regT1, regT0);
     map(m_bytecodeIndex + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0);
 }
     emitStore(dst, regT1, regT0);
     map(m_bytecodeIndex + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0);
 }
@@ -288,35 +297,16 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
     unsigned base = currentInstruction[2].u.operand;
     unsigned property = currentInstruction[3].u.operand;
 
     unsigned base = currentInstruction[2].u.operand;
     unsigned property = currentInstruction[3].u.operand;
 
-    // The slow void JIT::emitSlow_that handles accesses to arrays (below) may jump back up to here. 
-    Label callGetByValJITStub(this);
-
     linkSlowCase(iter); // property int32 check
     linkSlowCaseIfNotJSCell(iter, base); // base cell check
     linkSlowCase(iter); // base array check
     linkSlowCase(iter); // property int32 check
     linkSlowCaseIfNotJSCell(iter, base); // base cell check
     linkSlowCase(iter); // base array check
+    linkSlowCase(iter); // vector length check
+    linkSlowCase(iter); // empty value
 
     JITStubCall stubCall(this, cti_op_get_by_val);
     stubCall.addArgument(base);
     stubCall.addArgument(property);
     stubCall.call(dst);
 
     JITStubCall stubCall(this, cti_op_get_by_val);
     stubCall.addArgument(base);
     stubCall.addArgument(property);
     stubCall.call(dst);
-
-    emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
-
-    linkSlowCase(iter); // array fast cut-off check
-
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT0);
-    branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(ArrayStorage, m_vectorLength)), callGetByValJITStub);
-
-    // Missed the fast region, but it is still in the vector.
-    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), regT1); // tag
-    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0); // payload
-
-    // FIXME: Maybe we can optimize this comparison to JSValue().
-    Jump skip = branch32(NotEqual, regT0, Imm32(0));
-    branch32(Equal, regT1, Imm32(JSValue::CellTag), callGetByValJITStub);
-
-    skip.link(this);
-    emitStore(dst, regT1, regT0);
 }
 
 void JIT::emit_op_put_by_val(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_put_by_val(Instruction* currentInstruction)
@@ -330,24 +320,27 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3);
+    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength))));
 
 
-    Jump inFastVector = branch32(Below, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_fastAccessCutoff)));
-
-    // Check if the access is within the vector.
-    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_vectorLength))));
-
-    // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location.
-    // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff. 
-    Jump skip = branch32(NotEqual, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), Imm32(JSValue::CellTag));
-    addSlowCase(branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), Imm32(0)));
-    skip.link(this);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3);
 
 
-    inFastVector.link(this);
+    Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), Imm32(JSValue::EmptyValueTag));
 
 
+    Label storeResult(this);
     emitLoad(value, regT1, regT0);
     store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); // payload
     store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4)); // tag
     emitLoad(value, regT1, regT0);
     store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); // payload
     store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4)); // tag
+    Jump end = jump();
+
+    empty.link(this);
+    add32(Imm32(1), Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+    branch32(Below, regT2, Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_length))).linkTo(storeResult, this);
+
+    add32(Imm32(1), regT2, regT0);
+    store32(regT0, Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_length)));
+    jump().linkTo(storeResult, this);
+
+    end.link(this);
 }
 
 void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -359,24 +352,13 @@ void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCas
     linkSlowCase(iter); // property int32 check
     linkSlowCaseIfNotJSCell(iter, base); // base cell check
     linkSlowCase(iter); // base not array check
     linkSlowCase(iter); // property int32 check
     linkSlowCaseIfNotJSCell(iter, base); // base cell check
     linkSlowCase(iter); // base not array check
+    linkSlowCase(iter); // in vector check
 
     JITStubCall stubPutByValCall(this, cti_op_put_by_val);
     stubPutByValCall.addArgument(base);
     stubPutByValCall.addArgument(property);
     stubPutByValCall.addArgument(value);
     stubPutByValCall.call();
 
     JITStubCall stubPutByValCall(this, cti_op_put_by_val);
     stubPutByValCall.addArgument(base);
     stubPutByValCall.addArgument(property);
     stubPutByValCall.addArgument(value);
     stubPutByValCall.call();
-
-    emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
-
-    // Slow cases for immediate int accesses to arrays.
-    linkSlowCase(iter); // in vector check
-    linkSlowCase(iter); // written to slot check
-
-    JITStubCall stubCall(this, cti_op_put_by_val_array);
-    stubCall.addArgument(regT1, regT0);
-    stubCall.addArgument(regT2);
-    stubCall.addArgument(value);
-    stubCall.call();
 }
 
 void JIT::emit_op_get_by_id(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_get_by_id(Instruction* currentInstruction)
@@ -397,6 +379,9 @@ void JIT::compileGetByIdHotPath()
     // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump
     // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label
     // to jump back to if one of these trampolies finds a match.
     // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump
     // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label
     // to jump back to if one of these trampolies finds a match.
+
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
+    
     Label hotPathBegin(this);
     m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
     m_propertyAccessInstructionIndex++;
     Label hotPathBegin(this);
     m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
     m_propertyAccessInstructionIndex++;
@@ -419,6 +404,8 @@ void JIT::compileGetByIdHotPath()
 
     Label putResult(this);
     ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);
 
     Label putResult(this);
     ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);
+
+    END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
 }
 
 void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -440,13 +427,18 @@ void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<Sl
     linkSlowCaseIfNotJSCell(iter, base);
     linkSlowCase(iter);
 
     linkSlowCaseIfNotJSCell(iter, base);
     linkSlowCase(iter);
 
-    Label coldPathBegin(this);
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
 
 
+#ifndef NDEBUG
+    Label coldPathBegin(this);
+#endif
     JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
     stubCall.addArgument(regT1, regT0);
     stubCall.addArgument(ImmPtr(ident));
     Call call = stubCall.call(dst);
 
     JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
     stubCall.addArgument(regT1, regT0);
     stubCall.addArgument(ImmPtr(ident));
     Call call = stubCall.call(dst);
 
+    END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
+
     ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall);
 
     // Track the location of the call; this will be used to recover patch information.
     ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall);
 
     // Track the location of the call; this will be used to recover patch information.
@@ -467,6 +459,8 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
 
     emitJumpSlowCaseIfNotJSCell(base, regT1);
 
 
     emitJumpSlowCaseIfNotJSCell(base, regT1);
 
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById);
+
     Label hotPathBegin(this);
     m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
     m_propertyAccessInstructionIndex++;
     Label hotPathBegin(this);
     m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
     m_propertyAccessInstructionIndex++;
@@ -484,6 +478,9 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
 
     DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT0, patchGetByIdDefaultOffset)); // payload
     DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT0, patchGetByIdDefaultOffset)); // tag
 
     DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT0, patchGetByIdDefaultOffset)); // payload
     DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT0, patchGetByIdDefaultOffset)); // tag
+
+    END_UNINTERRUPTED_SEQUENCE(sequencePutById);
+
     ASSERT(differenceBetween(hotPathBegin, displacementLabel1) == patchOffsetPutByIdPropertyMapOffset1);
     ASSERT(differenceBetween(hotPathBegin, displacementLabel2) == patchOffsetPutByIdPropertyMapOffset2);
 }
     ASSERT(differenceBetween(hotPathBegin, displacementLabel1) == patchOffsetPutByIdPropertyMapOffset1);
     ASSERT(differenceBetween(hotPathBegin, displacementLabel2) == patchOffsetPutByIdPropertyMapOffset2);
 }
@@ -545,22 +542,26 @@ void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID res
     load32(Address(temp, offset + 4), resultTag);
 }
 
     load32(Address(temp, offset + 4), resultTag);
 }
 
+void JIT::testPrototype(Structure* structure, JumpList& failureCases)
+{
+    if (structure->m_prototype.isNull())
+        return;
+
+    failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&asCell(structure->m_prototype)->m_structure), ImmPtr(asCell(structure->m_prototype)->m_structure)));
+}
+
 void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
 {
     // It is assumed that regT0 contains the basePayload and regT1 contains the baseTag.  The value can be found on the stack.
 
     JumpList failureCases;
     failureCases.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
 void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
 {
     // It is assumed that regT0 contains the basePayload and regT1 contains the baseTag.  The value can be found on the stack.
 
     JumpList failureCases;
     failureCases.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
-
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    failureCases.append(branchPtr(NotEqual, regT2, ImmPtr(oldStructure)));
+    failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
+    testPrototype(oldStructure, failureCases);
 
     // Verify that nothing in the prototype chain has a setter for this property. 
 
     // Verify that nothing in the prototype chain has a setter for this property. 
-    for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
-        loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
-        loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-        failureCases.append(branchPtr(NotEqual, regT2, ImmPtr(it->get())));
-    }
+    for (RefPtr<Structure>* it = chain->head(); *it; ++it)
+        testPrototype(it->get(), failureCases);
 
     // Reallocate property storage if needed.
     Call callTarget;
 
     // Reallocate property storage if needed.
     Call callTarget;
@@ -634,7 +635,7 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + 4); // tag
 }
 
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + 4); // tag
 }
 
-void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto)
+void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
 {
     RepatchBuffer repatchBuffer(codeBlock);
 
 {
     RepatchBuffer repatchBuffer(codeBlock);
 
@@ -651,6 +652,8 @@ void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodC
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
+
+    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
 }
 
 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
 }
 
 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
@@ -727,7 +730,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     move(ImmPtr(prototypeStructure), regT3);
     Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
 #else
     move(ImmPtr(prototypeStructure), regT3);
     Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
 #else
@@ -807,7 +810,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     move(ImmPtr(prototypeStructure), regT3);
     Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
 #else
     move(ImmPtr(prototypeStructure), regT3);
     Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
 #else
@@ -860,7 +863,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         move(ImmPtr(currStructure), regT3);
         bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
 #else
         move(ImmPtr(currStructure), regT3);
         bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
 #else
@@ -915,7 +918,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         move(ImmPtr(currStructure), regT3);
         bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
 #else
         move(ImmPtr(currStructure), regT3);
         bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
 #else
@@ -952,16 +955,83 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
 
 #endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
 
 #endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
+void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID structure, RegisterID offset)
+{
+    ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t));
+    ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t));
+    ASSERT(sizeof(JSValue) == 8);
+
+    Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity));
+    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage)+OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
+    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage)+OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
+    Jump finishedLoad = jump();
+    notUsingInlineStorage.link(this);
+    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
+    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
+    finishedLoad.link(this);
+}
+
+void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned base = currentInstruction[2].u.operand;
+    unsigned property = currentInstruction[3].u.operand;
+    unsigned expected = currentInstruction[4].u.operand;
+    unsigned iter = currentInstruction[5].u.operand;
+    unsigned i = currentInstruction[6].u.operand;
+
+    emitLoad2(property, regT1, regT0, base, regT3, regT2);
+    emitJumpSlowCaseIfNotJSCell(property, regT1);
+    addSlowCase(branchPtr(NotEqual, regT0, payloadFor(expected)));
+    // Property registers are now available as the property is known
+    emitJumpSlowCaseIfNotJSCell(base, regT3);
+    emitLoadPayload(iter, regT1);
+    
+    // Test base's structure
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
+    addSlowCase(branchPtr(NotEqual, regT0, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))));
+    load32(addressFor(i), regT3);
+    sub32(Imm32(1), regT3);
+    addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots))));
+    compileGetDirectOffset(regT2, regT1, regT0, regT0, regT3);    
+
+    emitStore(dst, regT1, regT0);
+    map(m_bytecodeIndex + OPCODE_LENGTH(op_get_by_pname), dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned base = currentInstruction[2].u.operand;
+    unsigned property = currentInstruction[3].u.operand;
+    
+    linkSlowCaseIfNotJSCell(iter, property);
+    linkSlowCase(iter);
+    linkSlowCaseIfNotJSCell(iter, base);
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+    
+    JITStubCall stubCall(this, cti_op_get_by_val);
+    stubCall.addArgument(base);
+    stubCall.addArgument(property);
+    stubCall.call(dst);
+}
+
 #else // USE(JSVALUE32_64)
 
 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
 {
 #else // USE(JSVALUE32_64)
 
 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
 {
-    emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned base = currentInstruction[2].u.operand;
+    unsigned property = currentInstruction[3].u.operand;
+
+    emitGetVirtualRegisters(base, regT0, property, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT1);
 #if USE(JSVALUE64)
     // This is technically incorrect - we're zero-extending an int32.  On the hot path this doesn't matter.
     emitJumpSlowCaseIfNotImmediateInteger(regT1);
 #if USE(JSVALUE64)
     // This is technically incorrect - we're zero-extending an int32.  On the hot path this doesn't matter.
-    // We check the value as if it was a uint32 against the m_fastAccessCutoff - which will always fail if
-    // number was signed since m_fastAccessCutoff is always less than intmax (since the total allocation
+    // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if
+    // number was signed since m_vectorLength is always less than intmax (since the total allocation
     // size is always less than 4Gb).  As such zero extending wil have been correct (and extending the value
     // to 64-bits is necessary since it's used in the address calculation.  We zero extend rather than sign
     // extending since it makes it easier to re-tag the value in the slow case.
     // size is always less than 4Gb).  As such zero extending wil have been correct (and extending the value
     // to 64-bits is necessary since it's used in the address calculation.  We zero extend rather than sign
     // extending since it makes it easier to re-tag the value in the slow case.
@@ -969,21 +1039,81 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
 #else
     emitFastArithImmToInt(regT1);
 #endif
 #else
     emitFastArithImmToInt(regT1);
 #endif
-    emitJumpSlowCaseIfNotJSCell(regT0);
+    emitJumpSlowCaseIfNotJSCell(regT0, base);
     addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
 
     addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
 
-    // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
-    addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_fastAccessCutoff))));
+    addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength))));
 
 
-    // Get the value from the vector
     loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0);
     loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0);
-    emitPutVirtualRegister(currentInstruction[1].u.operand);
+    addSlowCase(branchTestPtr(Zero, regT0));
+
+    emitPutVirtualRegister(dst);
+}
+
+void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch)
+{
+    ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t));
+    ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t));
+
+    Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity));
+    loadPtr(BaseIndex(base, offset, ScalePtr, OBJECT_OFFSETOF(JSObject, m_inlineStorage)), result);
+    Jump finishedLoad = jump();
+    notUsingInlineStorage.link(this);
+    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), scratch);
+    loadPtr(BaseIndex(scratch, offset, ScalePtr, 0), result);
+    finishedLoad.link(this);
+}
+
+void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned base = currentInstruction[2].u.operand;
+    unsigned property = currentInstruction[3].u.operand;
+    unsigned expected = currentInstruction[4].u.operand;
+    unsigned iter = currentInstruction[5].u.operand;
+    unsigned i = currentInstruction[6].u.operand;
+
+    emitGetVirtualRegister(property, regT0);
+    addSlowCase(branchPtr(NotEqual, regT0, addressFor(expected)));
+    emitGetVirtualRegisters(base, regT0, iter, regT1);
+    emitJumpSlowCaseIfNotJSCell(regT0, base);
+
+    // Test base's structure
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+    addSlowCase(branchPtr(NotEqual, regT2, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))));
+    load32(addressFor(i), regT3);
+    sub32(Imm32(1), regT3);
+    addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots))));
+    compileGetDirectOffset(regT0, regT0, regT2, regT3, regT1);
+
+    emitPutVirtualRegister(dst, regT0);
+}
+
+void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned base = currentInstruction[2].u.operand;
+    unsigned property = currentInstruction[3].u.operand;
+
+    linkSlowCase(iter);
+    linkSlowCaseIfNotJSCell(iter, base);
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+
+    JITStubCall stubCall(this, cti_op_get_by_val);
+    stubCall.addArgument(base, regT2);
+    stubCall.addArgument(property, regT2);
+    stubCall.call(dst);
 }
 
 void JIT::emit_op_put_by_val(Instruction* currentInstruction)
 {
 }
 
 void JIT::emit_op_put_by_val(Instruction* currentInstruction)
 {
-    emitGetVirtualRegisters(currentInstruction[1].u.operand, regT0, currentInstruction[2].u.operand, regT1);
+    unsigned base = currentInstruction[1].u.operand;
+    unsigned property = currentInstruction[2].u.operand;
+    unsigned value = currentInstruction[3].u.operand;
+
+    emitGetVirtualRegisters(base, regT0, property, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT1);
 #if USE(JSVALUE64)
     // See comment in op_get_by_val.
     emitJumpSlowCaseIfNotImmediateInteger(regT1);
 #if USE(JSVALUE64)
     // See comment in op_get_by_val.
@@ -991,23 +1121,29 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
 #else
     emitFastArithImmToInt(regT1);
 #endif
 #else
     emitFastArithImmToInt(regT1);
 #endif
-    emitJumpSlowCaseIfNotJSCell(regT0);
+    emitJumpSlowCaseIfNotJSCell(regT0, base);
     addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
     addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
+    addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength))));
 
 
-    // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
-    Jump inFastVector = branch32(Below, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_fastAccessCutoff)));
-    // No; oh well, check if the access if within the vector - if so, we may still be okay.
-    addSlowCase(branch32(AboveOrEqual, regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_vectorLength))));
 
 
-    // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location.
-    // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff. 
-    addSlowCase(branchTestPtr(Zero, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
+    Jump empty = branchTestPtr(Zero, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
 
 
-    // All good - put the value into the array.
-    inFastVector.link(this);
-    emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
+    Label storeResult(this);
+    emitGetVirtualRegister(value, regT0);
     storePtr(regT0, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
     storePtr(regT0, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+    Jump end = jump();
+    
+    empty.link(this);
+    add32(Imm32(1), Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+    branch32(Below, regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length))).linkTo(storeResult, this);
+
+    move(regT1, regT0);
+    add32(Imm32(1), regT0);
+    store32(regT0, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length)));
+    jump().linkTo(storeResult, this);
+
+    end.link(this);
 }
 
 void JIT::emit_op_put_by_index(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_put_by_index(Instruction* currentInstruction)
@@ -1120,18 +1256,25 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     // Do the method check - check the object & its prototype's structure inline (this is the common case).
     m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_propertyAccessInstructionIndex));
     MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
     // Do the method check - check the object & its prototype's structure inline (this is the common case).
     m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_propertyAccessInstructionIndex));
     MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
+
     Jump notCell = emitJumpIfNotJSCell(regT0);
     Jump notCell = emitJumpIfNotJSCell(regT0);
+
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
+
     Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT1);
     Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
 
     // This will be relinked to load the function without doing a load.
     DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0);
     Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT1);
     Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
 
     // This will be relinked to load the function without doing a load.
     DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0);
+
+    END_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
+
     Jump match = jump();
 
     Jump match = jump();
 
-    ASSERT(differenceBetween(info.structureToCompare, protoObj) == patchOffsetMethodCheckProtoObj);
-    ASSERT(differenceBetween(info.structureToCompare, protoStructureToCompare) == patchOffsetMethodCheckProtoStruct);
-    ASSERT(differenceBetween(info.structureToCompare, putFunction) == patchOffsetMethodCheckPutFunction);
+    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoObj), patchOffsetMethodCheckProtoObj);
+    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoStructureToCompare), patchOffsetMethodCheckProtoStruct);
+    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, putFunction), patchOffsetMethodCheckPutFunction);
 
     // Link the failure cases here.
     notCell.link(this);
 
     // Link the failure cases here.
     notCell.link(this);
@@ -1190,25 +1333,30 @@ void JIT::compileGetByIdHotPath(int, int baseVReg, Identifier*, unsigned propert
 
     emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
 
 
     emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
 
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
+
     Label hotPathBegin(this);
     m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
 
     DataLabelPtr structureToCompare;
     Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     addSlowCase(structureCheck);
     Label hotPathBegin(this);
     m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
 
     DataLabelPtr structureToCompare;
     Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     addSlowCase(structureCheck);
-    ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetGetByIdStructure);
-    ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase)
 
     Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
     Label externalLoadComplete(this);
 
     Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
     Label externalLoadComplete(this);
-    ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetGetByIdExternalLoad);
-    ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthGetByIdExternalLoad);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, externalLoad), patchOffsetGetByIdExternalLoad);
+    ASSERT_JIT_OFFSET(differenceBetween(externalLoad, externalLoadComplete), patchLengthGetByIdExternalLoad);
 
     DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);
 
     DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);
-    ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetGetByIdPropertyMapOffset);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel), patchOffsetGetByIdPropertyMapOffset);
 
     Label putResult(this);
 
     Label putResult(this);
-    ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);
+
+    END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
+
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, putResult), patchOffsetGetByIdPutResult);
 }
 
 void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -1231,6 +1379,8 @@ void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident
     linkSlowCaseIfNotJSCell(iter, baseVReg);
     linkSlowCase(iter);
 
     linkSlowCaseIfNotJSCell(iter, baseVReg);
     linkSlowCase(iter);
 
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
+
 #ifndef NDEBUG
     Label coldPathBegin(this);
 #endif
 #ifndef NDEBUG
     Label coldPathBegin(this);
 #endif
@@ -1239,7 +1389,9 @@ void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident
     stubCall.addArgument(ImmPtr(ident));
     Call call = stubCall.call(resultVReg);
 
     stubCall.addArgument(ImmPtr(ident));
     Call call = stubCall.call(resultVReg);
 
-    ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall);
+    END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
+
+    ASSERT_JIT_OFFSET(differenceBetween(coldPathBegin, call), patchOffsetGetByIdSlowCaseCall);
 
     // Track the location of the call; this will be used to recover patch information.
     m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
 
     // Track the location of the call; this will be used to recover patch information.
     m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
@@ -1262,22 +1414,27 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
     // Jump to a slow case if either the base object is an immediate, or if the Structure does not match.
     emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
 
     // Jump to a slow case if either the base object is an immediate, or if the Structure does not match.
     emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
 
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById);
+
     Label hotPathBegin(this);
     m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
 
     // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.
     DataLabelPtr structureToCompare;
     addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
     Label hotPathBegin(this);
     m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
 
     // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.
     DataLabelPtr structureToCompare;
     addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
-    ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetPutByIdStructure);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure);
 
     // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
     Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
     Label externalLoadComplete(this);
 
     // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
     Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
     Label externalLoadComplete(this);
-    ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetPutByIdExternalLoad);
-    ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthPutByIdExternalLoad);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, externalLoad), patchOffsetPutByIdExternalLoad);
+    ASSERT_JIT_OFFSET(differenceBetween(externalLoad, externalLoadComplete), patchLengthPutByIdExternalLoad);
 
     DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset));
 
     DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset));
-    ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetPutByIdPropertyMapOffset);
+
+    END_UNINTERRUPTED_SEQUENCE(sequencePutById);
+
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel), patchOffsetPutByIdPropertyMapOffset);
 }
 
 void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -1334,35 +1491,27 @@ void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID res
     } 
 }
 
     } 
 }
 
+void JIT::testPrototype(Structure* structure, JumpList& failureCases)
+{
+    if (structure->m_prototype.isNull())
+        return;
+
+    move(ImmPtr(&asCell(structure->m_prototype)->m_structure), regT2);
+    move(ImmPtr(asCell(structure->m_prototype)->m_structure), regT3);
+    failureCases.append(branchPtr(NotEqual, Address(regT2), regT3));
+}
+
 void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
 {
     JumpList failureCases;
     // Check eax is an object of the right Structure.
     failureCases.append(emitJumpIfNotJSCell(regT0));
     failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
 void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
 {
     JumpList failureCases;
     // Check eax is an object of the right Structure.
     failureCases.append(emitJumpIfNotJSCell(regT0));
     failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
-    JumpList successCases;
-
-    // ecx = baseObject
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    // proto(ecx) = baseObject->structure()->prototype()
-    failureCases.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType)));
+    testPrototype(oldStructure, failureCases);
 
 
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
-    
     // ecx = baseObject->m_structure
     // ecx = baseObject->m_structure
-    for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
-        // null check the prototype
-        successCases.append(branchPtr(Equal, regT2, ImmPtr(JSValue::encode(jsNull()))));
-
-        // Check the structure id
-        failureCases.append(branchPtr(NotEqual, Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(it->get())));
-        
-        loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-        failureCases.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType)));
-        loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
-    }
-
-    successCases.link(this);
+    for (RefPtr<Structure>* it = chain->head(); *it; ++it)
+        testPrototype(it->get(), failureCases);
 
     Call callTarget;
 
 
     Call callTarget;
 
@@ -1380,7 +1529,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
         stubCall.addArgument(Imm32(oldStructure->propertyStorageCapacity()));
         stubCall.addArgument(Imm32(newStructure->propertyStorageCapacity()));
         stubCall.call(regT0);
         stubCall.addArgument(Imm32(oldStructure->propertyStorageCapacity()));
         stubCall.addArgument(Imm32(newStructure->propertyStorageCapacity()));
         stubCall.call(regT0);
-        emitGetJITStubArg(3, regT1);
+        emitGetJITStubArg(2, regT1);
 
         restoreReturnAddressBeforeReturn(regT3);
     }
 
         restoreReturnAddressBeforeReturn(regT3);
     }
@@ -1436,7 +1585,7 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset), offset);
 }
 
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset), offset);
 }
 
-void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto)
+void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
 {
     RepatchBuffer repatchBuffer(codeBlock);
 
 {
     RepatchBuffer repatchBuffer(codeBlock);
 
@@ -1453,6 +1602,8 @@ void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodC
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
     repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
+
+    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
 }
 
 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
 }
 
 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
@@ -1525,7 +1676,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     move(ImmPtr(prototypeStructure), regT3);
     Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
 #else
     move(ImmPtr(prototypeStructure), regT3);
     Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
 #else
@@ -1600,7 +1751,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     move(ImmPtr(prototypeStructure), regT3);
     Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
 #else
     move(ImmPtr(prototypeStructure), regT3);
     Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
 #else
@@ -1653,7 +1804,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         move(ImmPtr(currStructure), regT3);
         bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
 #else
         move(ImmPtr(currStructure), regT3);
         bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
 #else
@@ -1706,7 +1857,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
         move(ImmPtr(currStructure), regT3);
         bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
 #else
         move(ImmPtr(currStructure), regT3);
         bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
 #else
index cb5354b9b8c3cf453dbd241f00c650777b3562a7..cfbd7dc68befd618cae23fba2631f787c6c19c80 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef JITStubCall_h
 #define JITStubCall_h
 
 #ifndef JITStubCall_h
 #define JITStubCall_h
 
-#include <wtf/Platform.h>
+#include "MacroAssemblerCodeRef.h"
 
 #if ENABLE(JIT)
 
 
 #if ENABLE(JIT)
 
@@ -36,58 +36,58 @@ namespace JSC {
     public:
         JITStubCall(JIT* jit, JSObject* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
     public:
         JITStubCall(JIT* jit, JSObject* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
-            , m_stub(reinterpret_cast<void*>(stub))
+            , m_stub(stub)
             , m_returnType(Cell)
             , m_returnType(Cell)
-            , m_stackIndex(stackIndexStart)
+            , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
         {
         }
 
         JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
         {
         }
 
         JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
-            , m_stub(reinterpret_cast<void*>(stub))
+            , m_stub(stub)
             , m_returnType(Cell)
             , m_returnType(Cell)
-            , m_stackIndex(stackIndexStart)
+            , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
         {
         }
 
         JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
         {
         }
 
         JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
-            , m_stub(reinterpret_cast<void*>(stub))
+            , m_stub(stub)
             , m_returnType(VoidPtr)
             , m_returnType(VoidPtr)
-            , m_stackIndex(stackIndexStart)
+            , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
         {
         }
 
         JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
         {
         }
 
         JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
-            , m_stub(reinterpret_cast<void*>(stub))
+            , m_stub(stub)
             , m_returnType(Int)
             , m_returnType(Int)
-            , m_stackIndex(stackIndexStart)
+            , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
         {
         }
 
         JITStubCall(JIT* jit, bool (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
         {
         }
 
         JITStubCall(JIT* jit, bool (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
-            , m_stub(reinterpret_cast<void*>(stub))
+            , m_stub(stub)
             , m_returnType(Int)
             , m_returnType(Int)
-            , m_stackIndex(stackIndexStart)
+            , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
         {
         }
 
         JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
         {
         }
 
         JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
-            , m_stub(reinterpret_cast<void*>(stub))
+            , m_stub(stub)
             , m_returnType(Void)
             , m_returnType(Void)
-            , m_stackIndex(stackIndexStart)
+            , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
         {
         }
 
 #if USE(JSVALUE32_64)
         JITStubCall(JIT* jit, EncodedJSValue (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
         {
         }
 
 #if USE(JSVALUE32_64)
         JITStubCall(JIT* jit, EncodedJSValue (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
             : m_jit(jit)
-            , m_stub(reinterpret_cast<void*>(stub))
+            , m_stub(stub)
             , m_returnType(Value)
             , m_returnType(Value)
-            , m_stackIndex(stackIndexStart)
+            , m_stackIndex(JITSTACKFRAME_ARGS_INDEX)
         {
         }
 #endif
         {
         }
 #endif
@@ -145,7 +145,7 @@ namespace JSC {
 
         void getArgument(size_t argumentNumber, JIT::RegisterID tag, JIT::RegisterID payload)
         {
 
         void getArgument(size_t argumentNumber, JIT::RegisterID tag, JIT::RegisterID payload)
         {
-            size_t stackIndex = stackIndexStart + (argumentNumber * stackIndexStep);
+            size_t stackIndex = JITSTACKFRAME_ARGS_INDEX + (argumentNumber * stackIndexStep);
             m_jit->peek(payload, stackIndex);
             m_jit->peek(tag, stackIndex + 1);
         }
             m_jit->peek(payload, stackIndex);
             m_jit->peek(tag, stackIndex + 1);
         }
@@ -171,7 +171,7 @@ namespace JSC {
 
             m_jit->restoreArgumentReference();
             JIT::Call call = m_jit->call();
 
             m_jit->restoreArgumentReference();
             JIT::Call call = m_jit->call();
-            m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeIndex, m_stub));
+            m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeIndex, m_stub.value()));
 
 #if ENABLE(OPCODE_SAMPLING)
             if (m_jit->m_bytecodeIndex != (unsigned)-1)
 
 #if ENABLE(OPCODE_SAMPLING)
             if (m_jit->m_bytecodeIndex != (unsigned)-1)
@@ -222,10 +222,9 @@ namespace JSC {
 
     private:
         static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1;
 
     private:
         static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1;
-        static const size_t stackIndexStart = 1; // Index 0 is reserved for restoreArgumentReference().
 
         JIT* m_jit;
 
         JIT* m_jit;
-        void* m_stub;
+        FunctionPtr m_stub;
         enum { Void, VoidPtr, Int, Value, Cell } m_returnType;
         size_t m_stackIndex;
     };
         enum { Void, VoidPtr, Int, Value, Cell } m_returnType;
         size_t m_stackIndex;
     };
index a7011e8b950093ee5f6ce72b99adc114341f9782..bf5168b45c2d8907fb51292c9fea081c585a7898 100644 (file)
@@ -56,6 +56,7 @@
 #include "RegExpPrototype.h"
 #include "Register.h"
 #include "SamplingTool.h"
 #include "RegExpPrototype.h"
 #include "Register.h"
 #include "SamplingTool.h"
+#include <wtf/StdLibExtras.h>
 #include <stdarg.h>
 #include <stdio.h>
 
 #include <stdarg.h>
 #include <stdio.h>
 
@@ -63,15 +64,46 @@ using namespace std;
 
 namespace JSC {
 
 
 namespace JSC {
 
-#if PLATFORM(DARWIN) || PLATFORM(WIN_OS)
+#if OS(DARWIN) || OS(WINDOWS)
 #define SYMBOL_STRING(name) "_" #name
 #else
 #define SYMBOL_STRING(name) #name
 #endif
 
 #define SYMBOL_STRING(name) "_" #name
 #else
 #define SYMBOL_STRING(name) #name
 #endif
 
+#if OS(IPHONE_OS)
+#define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name)
+#else
+#define THUMB_FUNC_PARAM(name)
+#endif
+
+#if OS(LINUX) && CPU(X86_64)
+#define SYMBOL_STRING_RELOCATION(name) #name "@plt"
+#else
+#define SYMBOL_STRING_RELOCATION(name) SYMBOL_STRING(name)
+#endif
+
+#if OS(DARWIN)
+    // Mach-O platform
+#define HIDE_SYMBOL(name) ".private_extern _" #name
+#elif OS(AIX)
+    // IBM's own file format
+#define HIDE_SYMBOL(name) ".lglobl " #name
+#elif   OS(LINUX)               \
+     || OS(FREEBSD)             \
+     || OS(OPENBSD)             \
+     || OS(SOLARIS)             \
+     || (OS(HPUX) && CPU(IA64)) \
+     || OS(SYMBIAN)             \
+     || OS(NETBSD)
+    // ELF platform
+#define HIDE_SYMBOL(name) ".hidden " #name
+#else
+#define HIDE_SYMBOL(name)
+#endif
+
 #if USE(JSVALUE32_64)
 
 #if USE(JSVALUE32_64)
 
-#if COMPILER(GCC) && PLATFORM(X86)
+#if COMPILER(GCC) && CPU(X86)
 
 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
 // need to change the assembly trampolines below to match.
 
 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
 // need to change the assembly trampolines below to match.
@@ -81,7 +113,9 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_
 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
 
 asm volatile (
 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
 
 asm volatile (
+".text\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+HIDE_SYMBOL(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "pushl %ebp" "\n"
     "movl %esp, %ebp" "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "pushl %ebp" "\n"
     "movl %esp, %ebp" "\n"
@@ -102,11 +136,12 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
     "movl %esp, %ecx" "\n"
 #endif
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
     "movl %esp, %ecx" "\n"
 #endif
-    "call " SYMBOL_STRING(cti_vm_throw) "\n"
+    "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
     "addl $0x3c, %esp" "\n"
     "popl %ebx" "\n"
     "popl %edi" "\n"
     "addl $0x3c, %esp" "\n"
     "popl %ebx" "\n"
     "popl %edi" "\n"
@@ -117,6 +152,7 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     
 asm volatile (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
     
 asm volatile (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "addl $0x3c, %esp" "\n"
     "popl %ebx" "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "addl $0x3c, %esp" "\n"
     "popl %ebx" "\n"
@@ -126,7 +162,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ret" "\n"
 );
     
     "ret" "\n"
 );
     
-#elif COMPILER(GCC) && PLATFORM(X86_64)
+#elif COMPILER(GCC) && CPU(X86_64)
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
@@ -141,6 +177,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+HIDE_SYMBOL(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "pushq %rbp" "\n"
     "movq %rsp, %rbp" "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "pushq %rbp" "\n"
     "movq %rsp, %rbp" "\n"
@@ -167,9 +204,10 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "movq %rsp, %rdi" "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "movq %rsp, %rdi" "\n"
-    "call " SYMBOL_STRING(cti_vm_throw) "\n"
+    "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
     "addq $0x48, %rsp" "\n"
     "popq %rbx" "\n"
     "popq %r15" "\n"
     "addq $0x48, %rsp" "\n"
     "popq %rbx" "\n"
     "popq %r15" "\n"
@@ -182,6 +220,7 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "addq $0x48, %rsp" "\n"
     "popq %rbx" "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "addq $0x48, %rsp" "\n"
     "popq %rbx" "\n"
@@ -193,7 +232,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ret" "\n"
 );
 
     "ret" "\n"
 );
 
-#elif COMPILER(GCC) && PLATFORM_ARM_ARCH(7)
+#elif COMPILER(GCC) && CPU(ARM_THUMB2)
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
@@ -203,8 +242,9 @@ asm volatile (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+HIDE_SYMBOL(ctiTrampoline) "\n"
 ".thumb" "\n"
 ".thumb" "\n"
-".thumb_func " SYMBOL_STRING(ctiTrampoline) "\n"
+".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "sub sp, sp, #0x3c" "\n"
     "str lr, [sp, #0x20]" "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "sub sp, sp, #0x3c" "\n"
     "str lr, [sp, #0x20]" "\n"
@@ -229,11 +269,12 @@ asm volatile (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 ".thumb" "\n"
 ".thumb" "\n"
-".thumb_func " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "cpy r0, sp" "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "cpy r0, sp" "\n"
-    "bl " SYMBOL_STRING(cti_vm_throw) "\n"
+    "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
     "ldr r6, [sp, #0x2c]" "\n"
     "ldr r5, [sp, #0x28]" "\n"
     "ldr r4, [sp, #0x24]" "\n"
     "ldr r6, [sp, #0x2c]" "\n"
     "ldr r5, [sp, #0x28]" "\n"
     "ldr r4, [sp, #0x24]" "\n"
@@ -247,7 +288,7 @@ asm volatile (
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 ".thumb" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 ".thumb" "\n"
-".thumb_func " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ldr r6, [sp, #0x2c]" "\n"
     "ldr r5, [sp, #0x28]" "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ldr r6, [sp, #0x2c]" "\n"
     "ldr r5, [sp, #0x28]" "\n"
@@ -257,7 +298,41 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "bx lr" "\n"
 );
 
     "bx lr" "\n"
 );
 
-#elif COMPILER(MSVC)
+#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
+
+asm volatile (
+".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+SYMBOL_STRING(ctiTrampoline) ":" "\n"
+    "stmdb sp!, {r1-r3}" "\n"
+    "stmdb sp!, {r4-r8, lr}" "\n"
+    "sub sp, sp, #68" "\n"
+    "mov r4, r2" "\n"
+    "mov r5, #512" "\n"
+    // r0 contains the code
+    "mov lr, pc" "\n"
+    "mov pc, r0" "\n"
+    "add sp, sp, #68" "\n"
+    "ldmia sp!, {r4-r8, lr}" "\n"
+    "add sp, sp, #12" "\n"
+    "mov pc, lr" "\n"
+);
+
+asm volatile (
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+    "mov r0, sp" "\n"
+    "bl " SYMBOL_STRING(cti_vm_throw) "\n"
+
+// Both has the same return sequence
+".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
+    "add sp, sp, #68" "\n"
+    "ldmia sp!, {r4-r8, lr}" "\n"
+    "add sp, sp, #12" "\n"
+    "mov pc, lr" "\n"
+);
+
+#elif COMPILER(MSVC) && CPU(X86)
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
@@ -321,11 +396,13 @@ extern "C" {
     }
 }
 
     }
 }
 
-#endif // COMPILER(GCC) && PLATFORM(X86)
+#else
+    #error "JIT not supported on this platform."
+#endif
 
 #else // USE(JSVALUE32_64)
 
 
 #else // USE(JSVALUE32_64)
 
-#if COMPILER(GCC) && PLATFORM(X86)
+#if COMPILER(GCC) && CPU(X86)
 
 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
 // need to change the assembly trampolines below to match.
 
 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
 // need to change the assembly trampolines below to match.
@@ -334,7 +411,9 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_
 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
 
 asm volatile (
 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
 
 asm volatile (
+".text\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+HIDE_SYMBOL(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "pushl %ebp" "\n"
     "movl %esp, %ebp" "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "pushl %ebp" "\n"
     "movl %esp, %ebp" "\n"
@@ -355,11 +434,12 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
     "movl %esp, %ecx" "\n"
 #endif
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
     "movl %esp, %ecx" "\n"
 #endif
-    "call " SYMBOL_STRING(cti_vm_throw) "\n"
+    "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
     "addl $0x1c, %esp" "\n"
     "popl %ebx" "\n"
     "popl %edi" "\n"
     "addl $0x1c, %esp" "\n"
     "popl %ebx" "\n"
     "popl %edi" "\n"
@@ -370,6 +450,7 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     
 asm volatile (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
     
 asm volatile (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "addl $0x1c, %esp" "\n"
     "popl %ebx" "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "addl $0x1c, %esp" "\n"
     "popl %ebx" "\n"
@@ -379,7 +460,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ret" "\n"
 );
     
     "ret" "\n"
 );
     
-#elif COMPILER(GCC) && PLATFORM(X86_64)
+#elif COMPILER(GCC) && CPU(X86_64)
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
@@ -387,12 +468,14 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
 
 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
 // need to change the assembly trampolines below to match.
 
 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
 // need to change the assembly trampolines below to match.
-COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
-COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline);
-COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline);
+COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
 
 asm volatile (
 
 asm volatile (
+".text\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+HIDE_SYMBOL(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "pushq %rbp" "\n"
     "movq %rsp, %rbp" "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "pushq %rbp" "\n"
     "movq %rsp, %rbp" "\n"
@@ -401,13 +484,20 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "pushq %r14" "\n"
     "pushq %r15" "\n"
     "pushq %rbx" "\n"
     "pushq %r14" "\n"
     "pushq %r15" "\n"
     "pushq %rbx" "\n"
+    // Form the JIT stubs area
+    "pushq %r9" "\n"
+    "pushq %r8" "\n"
+    "pushq %rcx" "\n"
+    "pushq %rdx" "\n"
+    "pushq %rsi" "\n"
+    "pushq %rdi" "\n"
     "subq $0x48, %rsp" "\n"
     "movq $512, %r12" "\n"
     "movq $0xFFFF000000000000, %r14" "\n"
     "movq $0xFFFF000000000002, %r15" "\n"
     "subq $0x48, %rsp" "\n"
     "movq $512, %r12" "\n"
     "movq $0xFFFF000000000000, %r14" "\n"
     "movq $0xFFFF000000000002, %r15" "\n"
-    "movq 0x90(%rsp), %r13" "\n"
-    "call *0x80(%rsp)" "\n"
-    "addq $0x48, %rsp" "\n"
+    "movq %rdx, %r13" "\n"
+    "call *%rdi" "\n"
+    "addq $0x78, %rsp" "\n"
     "popq %rbx" "\n"
     "popq %r15" "\n"
     "popq %r14" "\n"
     "popq %rbx" "\n"
     "popq %r15" "\n"
     "popq %r14" "\n"
@@ -419,10 +509,11 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "movq %rsp, %rdi" "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "movq %rsp, %rdi" "\n"
-    "call " SYMBOL_STRING(cti_vm_throw) "\n"
-    "addq $0x48, %rsp" "\n"
+    "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
+    "addq $0x78, %rsp" "\n"
     "popq %rbx" "\n"
     "popq %r15" "\n"
     "popq %r14" "\n"
     "popq %rbx" "\n"
     "popq %r15" "\n"
     "popq %r14" "\n"
@@ -434,8 +525,9 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
-    "addq $0x48, %rsp" "\n"
+    "addq $0x78, %rsp" "\n"
     "popq %rbx" "\n"
     "popq %r15" "\n"
     "popq %r14" "\n"
     "popq %rbx" "\n"
     "popq %r15" "\n"
     "popq %r14" "\n"
@@ -445,7 +537,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ret" "\n"
 );
 
     "ret" "\n"
 );
 
-#elif COMPILER(GCC) && PLATFORM_ARM_ARCH(7)
+#elif COMPILER(GCC) && CPU(ARM_THUMB2)
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
@@ -455,10 +547,11 @@ asm volatile (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+HIDE_SYMBOL(ctiTrampoline) "\n"
 ".thumb" "\n"
 ".thumb" "\n"
-".thumb_func " SYMBOL_STRING(ctiTrampoline) "\n"
+".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
-    "sub sp, sp, #0x3c" "\n"
+    "sub sp, sp, #0x40" "\n"
     "str lr, [sp, #0x20]" "\n"
     "str r4, [sp, #0x24]" "\n"
     "str r5, [sp, #0x28]" "\n"
     "str lr, [sp, #0x20]" "\n"
     "str r4, [sp, #0x24]" "\n"
     "str r5, [sp, #0x28]" "\n"
@@ -473,7 +566,7 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "ldr r5, [sp, #0x28]" "\n"
     "ldr r4, [sp, #0x24]" "\n"
     "ldr lr, [sp, #0x20]" "\n"
     "ldr r5, [sp, #0x28]" "\n"
     "ldr r4, [sp, #0x24]" "\n"
     "ldr lr, [sp, #0x20]" "\n"
-    "add sp, sp, #0x3c" "\n"
+    "add sp, sp, #0x40" "\n"
     "bx lr" "\n"
 );
 
     "bx lr" "\n"
 );
 
@@ -481,16 +574,17 @@ asm volatile (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 ".thumb" "\n"
 ".thumb" "\n"
-".thumb_func " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "cpy r0, sp" "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "cpy r0, sp" "\n"
-    "bl " SYMBOL_STRING(cti_vm_throw) "\n"
+    "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
     "ldr r6, [sp, #0x2c]" "\n"
     "ldr r5, [sp, #0x28]" "\n"
     "ldr r4, [sp, #0x24]" "\n"
     "ldr lr, [sp, #0x20]" "\n"
     "ldr r6, [sp, #0x2c]" "\n"
     "ldr r5, [sp, #0x28]" "\n"
     "ldr r4, [sp, #0x24]" "\n"
     "ldr lr, [sp, #0x20]" "\n"
-    "add sp, sp, #0x3c" "\n"
+    "add sp, sp, #0x40" "\n"
     "bx lr" "\n"
 );
 
     "bx lr" "\n"
 );
 
@@ -498,8 +592,9 @@ asm volatile (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 ".thumb" "\n"
 ".thumb" "\n"
-".thumb_func " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ldr r6, [sp, #0x2c]" "\n"
     "ldr r5, [sp, #0x28]" "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ldr r6, [sp, #0x2c]" "\n"
     "ldr r5, [sp, #0x28]" "\n"
@@ -509,7 +604,83 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "bx lr" "\n"
 );
 
     "bx lr" "\n"
 );
 
-#elif COMPILER(MSVC)
+#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
+
+asm volatile (
+".text\n"
+".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+HIDE_SYMBOL(ctiTrampoline) "\n"
+SYMBOL_STRING(ctiTrampoline) ":" "\n"
+    "stmdb sp!, {r1-r3}" "\n"
+    "stmdb sp!, {r4-r8, lr}" "\n"
+    "sub sp, sp, #36" "\n"
+    "mov r4, r2" "\n"
+    "mov r5, #512" "\n"
+    "mov lr, pc" "\n"
+    "mov pc, r0" "\n"
+    "add sp, sp, #36" "\n"
+    "ldmia sp!, {r4-r8, lr}" "\n"
+    "add sp, sp, #12" "\n"
+    "mov pc, lr" "\n"
+);
+
+asm volatile (
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+    "mov r0, sp" "\n"
+    "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
+
+// Both has the same return sequence
+".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
+SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
+    "add sp, sp, #36" "\n"
+    "ldmia sp!, {r4-r8, lr}" "\n"
+    "add sp, sp, #12" "\n"
+    "mov pc, lr" "\n"
+);
+
+#elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
+
+__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*)
+{
+    ARM
+    stmdb sp!, {r1-r3}
+    stmdb sp!, {r4-r8, lr}
+    sub sp, sp, #36
+    mov r4, r2
+    mov r5, #512
+    mov lr, pc
+    bx r0
+    add sp, sp, #36
+    ldmia sp!, {r4-r8, lr}
+    add sp, sp, #12
+    bx lr
+}
+
+__asm void ctiVMThrowTrampoline()
+{
+    ARM
+    PRESERVE8
+    mov r0, sp
+    bl cti_vm_throw
+    add sp, sp, #36
+    ldmia sp!, {r4-r8, lr}
+    add sp, sp, #12
+    bx lr
+}
+
+__asm void ctiOpThrowNotCaught()
+{
+    ARM
+    add sp, sp, #36
+    ldmia sp!, {r4-r8, lr}
+    add sp, sp, #12
+    bx lr
+}
+
+#elif COMPILER(MSVC) && CPU(X86)
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
 
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
@@ -572,7 +743,9 @@ extern "C" {
      }
 }
 
      }
 }
 
-#endif // COMPILER(GCC) && PLATFORM(X86)
+#else
+    #error "JIT not supported on this platform."
+#endif
 
 #endif // USE(JSVALUE32_64)
 
 
 #endif // USE(JSVALUE32_64)
 
@@ -584,9 +757,9 @@ extern "C" {
 
 JITThunks::JITThunks(JSGlobalData* globalData)
 {
 
 JITThunks::JITThunks(JSGlobalData* globalData)
 {
-    JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallPreLink, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &m_ctiNativeCallThunk);
+    JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &m_ctiNativeCallThunk);
 
 
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM_THUMB2)
     // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
     // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
     // macros.
     // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
     // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
     // macros.
@@ -599,7 +772,7 @@ JITThunks::JITThunks(JSGlobalData* globalData)
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == 0x34);
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == 0x38);
     // The fifth argument is the first item already on the stack.
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == 0x34);
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == 0x38);
     // The fifth argument is the first item already on the stack.
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == 0x3c);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == 0x40);
 
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == 0x1C);
 #endif
 
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == 0x1C);
 #endif
@@ -607,7 +780,7 @@ JITThunks::JITThunks(JSGlobalData* globalData)
 
 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
 
 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
-NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot)
+NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo)
 {
     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
 
 {
     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
 
@@ -634,17 +807,19 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
         return;
     }
 
         return;
     }
 
-    StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
-
     // Cache hit: Specialize instruction and ref Structures.
 
     // Structure transition, cache transition info
     if (slot.type() == PutPropertySlot::NewProperty) {
     // Cache hit: Specialize instruction and ref Structures.
 
     // Structure transition, cache transition info
     if (slot.type() == PutPropertySlot::NewProperty) {
-        StructureChain* prototypeChain = structure->prototypeChain(callFrame);
-        if (!prototypeChain->isCacheable() || structure->isDictionary()) {
+        if (structure->isDictionary()) {
             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
             return;
         }
             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
             return;
         }
+
+        // put_by_id_transition checks the prototype chain for setters.
+        normalizePrototypeChain(callFrame, baseCell);
+
+        StructureChain* prototypeChain = structure->prototypeChain(callFrame);
         stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
         JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress);
         return;
         stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
         JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress);
         return;
@@ -655,7 +830,7 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
     JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
 }
 
     JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
 }
 
-NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot)
+NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
 {
     // FIXME: Write a test that proves we need to check for recursion here just
     // like the interpreter does, then add a check for recursion.
 {
     // FIXME: Write a test that proves we need to check for recursion here just
     // like the interpreter does, then add a check for recursion.
@@ -694,11 +869,6 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
         return;
     }
 
         return;
     }
 
-    // In the interpreter the last structure is trapped here; in CTI we use the
-    // *_second method to achieve a similar (but not quite the same) effect.
-
-    StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
-
     // Cache hit: Specialize instruction and ref Structures.
 
     if (slot.slotBase() == baseValue) {
     // Cache hit: Specialize instruction and ref Structures.
 
     if (slot.slotBase() == baseValue) {
@@ -729,6 +899,8 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
         
         stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
 
         
         stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
 
+        ASSERT(!structure->isDictionary());
+        ASSERT(!slotBaseObject->structure()->isDictionary());
         JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), offset, returnAddress);
         return;
     }
         JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), offset, returnAddress);
         return;
     }
@@ -736,15 +908,11 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
     size_t offset = slot.cachedOffset();
     size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
     if (!count) {
     size_t offset = slot.cachedOffset();
     size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
     if (!count) {
-        stubInfo->opcodeID = op_get_by_id_generic;
+        stubInfo->accessType = access_get_by_id_generic;
         return;
     }
 
     StructureChain* prototypeChain = structure->prototypeChain(callFrame);
         return;
     }
 
     StructureChain* prototypeChain = structure->prototypeChain(callFrame);
-    if (!prototypeChain->isCacheable()) {
-        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
-        return;
-    }
     stubInfo->initGetByIdChain(structure, prototypeChain);
     JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, offset, returnAddress);
 }
     stubInfo->initGetByIdChain(structure, prototypeChain);
     JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, offset, returnAddress);
 }
@@ -842,7 +1010,7 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
         } \
     } while (0)
 
         } \
     } while (0)
 
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM_THUMB2)
 
 #define DEFINE_STUB_FUNCTION(rtype, op) \
     extern "C" { \
 
 #define DEFINE_STUB_FUNCTION(rtype, op) \
     extern "C" { \
@@ -852,8 +1020,9 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
         ".text" "\n" \
         ".align 2" "\n" \
         ".globl " SYMBOL_STRING(cti_##op) "\n" \
         ".text" "\n" \
         ".align 2" "\n" \
         ".globl " SYMBOL_STRING(cti_##op) "\n" \
+        HIDE_SYMBOL(cti_##op) "\n"             \
         ".thumb" "\n" \
         ".thumb" "\n" \
-        ".thumb_func " SYMBOL_STRING(cti_##op) "\n" \
+        ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \
         SYMBOL_STRING(cti_##op) ":" "\n" \
         "str lr, [sp, #0x1c]" "\n" \
         "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
         SYMBOL_STRING(cti_##op) ":" "\n" \
         "str lr, [sp, #0x1c]" "\n" \
         "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
@@ -862,6 +1031,56 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
         ); \
     rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
 
         ); \
     rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
 
+#elif CPU(ARM_TRADITIONAL) && COMPILER(GCC)
+
+#if USE(JSVALUE32_64)
+#define THUNK_RETURN_ADDRESS_OFFSET 64
+#else
+#define THUNK_RETURN_ADDRESS_OFFSET 32
+#endif
+
+COMPILE_ASSERT(offsetof(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET, JITStackFrame_thunkReturnAddress_offset_mismatch);
+
+#define DEFINE_STUB_FUNCTION(rtype, op) \
+    extern "C" { \
+        rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
+    }; \
+    asm volatile ( \
+        ".globl " SYMBOL_STRING(cti_##op) "\n" \
+        SYMBOL_STRING(cti_##op) ":" "\n" \
+        "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
+        "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
+        "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
+        "mov pc, lr" "\n" \
+        ); \
+    rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
+
+#elif CPU(ARM_TRADITIONAL) && COMPILER(RVCT)
+
+#define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
+
+/* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */
+
+/* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */
+/* The pattern "#xxx#" will be replaced with "xxx" */
+
+/*
+RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
+RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
+RVCT({)
+RVCT(    ARM)
+RVCT(    IMPORT JITStubThunked_#op#)
+RVCT(    str lr, [sp, #32])
+RVCT(    bl JITStubThunked_#op#)
+RVCT(    ldr lr, [sp, #32])
+RVCT(    bx lr)
+RVCT(})
+RVCT()
+*/
+
+/* Include the generated file */
+#include "GeneratedJITStubs_RVCT.h"
+
 #else
 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
 #endif
 #else
 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
 #endif
@@ -893,38 +1112,19 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
 
     JSValue v1 = stackFrame.args[0].jsValue();
     JSValue v2 = stackFrame.args[1].jsValue();
 
     JSValue v1 = stackFrame.args[0].jsValue();
     JSValue v2 = stackFrame.args[1].jsValue();
-
-    double left;
-    double right = 0.0;
-
-    bool rightIsNumber = v2.getNumber(right);
-    if (rightIsNumber && v1.getNumber(left))
-        return JSValue::encode(jsNumber(stackFrame.globalData, left + right));
-    
     CallFrame* callFrame = stackFrame.callFrame;
 
     CallFrame* callFrame = stackFrame.callFrame;
 
-    bool leftIsString = v1.isString();
-    if (leftIsString && v2.isString()) {
-        RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep());
-        if (UNLIKELY(!value)) {
-            throwOutOfMemoryError(callFrame);
-            VM_THROW_EXCEPTION();
-        }
-
-        return JSValue::encode(jsString(stackFrame.globalData, value.release()));
+    if (v1.isString()) {
+        JSValue result = v2.isString()
+            ? jsString(callFrame, asString(v1), asString(v2))
+            : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
+        CHECK_FOR_EXCEPTION_AT_END();
+        return JSValue::encode(result);
     }
 
     }
 
-    if (rightIsNumber & leftIsString) {
-        RefPtr<UString::Rep> value = v2.isInt32() ?
-            concatenate(asString(v1)->value().rep(), v2.asInt32()) :
-            concatenate(asString(v1)->value().rep(), right);
-
-        if (UNLIKELY(!value)) {
-            throwOutOfMemoryError(callFrame);
-            VM_THROW_EXCEPTION();
-        }
-        return JSValue::encode(jsString(stackFrame.globalData, value.release()));
-    }
+    double left = 0.0, right;
+    if (v1.getNumber(left) && v2.getNumber(right))
+        return JSValue::encode(jsNumber(stackFrame.globalData, left + right));
 
     // All other cases are pretty uncommon
     JSValue result = jsAddSlowCase(callFrame, v1, v2);
 
     // All other cases are pretty uncommon
     JSValue result = jsAddSlowCase(callFrame, v1, v2);
@@ -973,19 +1173,6 @@ DEFINE_STUB_FUNCTION(void, register_file_check)
     throwStackOverflowError(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS);
 }
 
     throwStackOverflowError(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS);
 }
 
-DEFINE_STUB_FUNCTION(int, op_loop_if_less)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    JSValue src1 = stackFrame.args[0].jsValue();
-    JSValue src2 = stackFrame.args[1].jsValue();
-    CallFrame* callFrame = stackFrame.callFrame;
-
-    bool result = jsLess(callFrame, src1, src2);
-    CHECK_FOR_EXCEPTION_AT_END();
-    return result;
-}
-
 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -1035,25 +1222,19 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
 DEFINE_STUB_FUNCTION(void, op_put_by_id)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(void, op_put_by_id)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
     CallFrame* callFrame = stackFrame.callFrame;
     Identifier& ident = stackFrame.args[1].identifier();
 
     PutPropertySlot slot;
     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
 
     CallFrame* callFrame = stackFrame.callFrame;
     Identifier& ident = stackFrame.args[1].identifier();
 
     PutPropertySlot slot;
     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
 
-    ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_id_second));
-
-    CHECK_FOR_EXCEPTION_AT_END();
-}
-
-DEFINE_STUB_FUNCTION(void, op_put_by_id_second)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
+    CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
+    StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
+    if (!stubInfo->seenOnce())
+        stubInfo->setSeen();
+    else
+        JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo);
 
 
-    PutPropertySlot slot;
-    stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
-    JITThunks::tryCachePutByID(stackFrame.callFrame, stackFrame.callFrame->codeBlock(), STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot);
     CHECK_FOR_EXCEPTION_AT_END();
 }
 
     CHECK_FOR_EXCEPTION_AT_END();
 }
 
@@ -1085,23 +1266,6 @@ DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
     return base;
 }
 
     return base;
 }
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    CallFrame* callFrame = stackFrame.callFrame;
-    Identifier& ident = stackFrame.args[1].identifier();
-
-    JSValue baseValue = stackFrame.args[0].jsValue();
-    PropertySlot slot(baseValue);
-    JSValue result = baseValue.get(callFrame, ident, slot);
-
-    ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_second));
-
-    CHECK_FOR_EXCEPTION_AT_END();
-    return JSValue::encode(result);
-}
-
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -1112,25 +1276,15 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
     JSValue baseValue = stackFrame.args[0].jsValue();
     PropertySlot slot(baseValue);
     JSValue result = baseValue.get(callFrame, ident, slot);
     JSValue baseValue = stackFrame.args[0].jsValue();
     PropertySlot slot(baseValue);
     JSValue result = baseValue.get(callFrame, ident, slot);
+    CHECK_FOR_EXCEPTION();
 
 
-    ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_method_check_second));
-
-    CHECK_FOR_EXCEPTION_AT_END();
-    return JSValue::encode(result);
-}
-
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_second)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
+    CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
+    MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
 
 
-    CallFrame* callFrame = stackFrame.callFrame;
-    Identifier& ident = stackFrame.args[1].identifier();
-
-    JSValue baseValue = stackFrame.args[0].jsValue();
-    PropertySlot slot(baseValue);
-    JSValue result = baseValue.get(callFrame, ident, slot);
-
-    CHECK_FOR_EXCEPTION();
+    if (!methodCallLinkInfo.seenOnce()) {
+        methodCallLinkInfo.setSeen();
+        return JSValue::encode(result);
+    }
 
     // If we successfully got something, then the base from which it is being accessed must
     // be an object.  (Assertion to ensure asObject() call below is safe, which comes after
 
     // If we successfully got something, then the base from which it is being accessed must
     // be an object.  (Assertion to ensure asObject() call below is safe, which comes after
@@ -1161,33 +1315,33 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_second)
 
         // The result fetched should always be the callee!
         ASSERT(result == JSValue(callee));
 
         // The result fetched should always be the callee!
         ASSERT(result == JSValue(callee));
-        MethodCallLinkInfo& methodCallLinkInfo = callFrame->codeBlock()->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
 
         // Check to see if the function is on the object's prototype.  Patch up the code to optimize.
 
         // Check to see if the function is on the object's prototype.  Patch up the code to optimize.
-        if (slot.slotBase() == structure->prototypeForLookup(callFrame))
-            JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, slotBaseObject);
+        if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
+            JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
+            return JSValue::encode(result);
+        }
+
         // Check to see if the function is on the object itself.
         // Since we generate the method-check to check both the structure and a prototype-structure (since this
         // is the common case) we have a problem - we need to patch the prototype structure check to do something
         // useful.  We could try to nop it out altogether, but that's a little messy, so lets do something simpler
         // for now.  For now it performs a check on a special object on the global object only used for this
         // purpose.  The object is in no way exposed, and as such the check will always pass.
         // Check to see if the function is on the object itself.
         // Since we generate the method-check to check both the structure and a prototype-structure (since this
         // is the common case) we have a problem - we need to patch the prototype structure check to do something
         // useful.  We could try to nop it out altogether, but that's a little messy, so lets do something simpler
         // for now.  For now it performs a check on a special object on the global object only used for this
         // purpose.  The object is in no way exposed, and as such the check will always pass.
-        else if (slot.slotBase() == baseValue)
-            JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject()->methodCallDummy());
-
-        // For now let any other case be cached as a normal get_by_id.
+        if (slot.slotBase() == baseValue) {
+            JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
+            return JSValue::encode(result);
+        }
     }
 
     // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
     }
 
     // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
-    ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
-
+    ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
     return JSValue::encode(result);
 }
 
     return JSValue::encode(result);
 }
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_second)
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
     CallFrame* callFrame = stackFrame.callFrame;
     Identifier& ident = stackFrame.args[1].identifier();
 
     CallFrame* callFrame = stackFrame.callFrame;
     Identifier& ident = stackFrame.args[1].identifier();
 
@@ -1195,7 +1349,12 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_second)
     PropertySlot slot(baseValue);
     JSValue result = baseValue.get(callFrame, ident, slot);
 
     PropertySlot slot(baseValue);
     JSValue result = baseValue.get(callFrame, ident, slot);
 
-    JITThunks::tryCacheGetByID(callFrame, callFrame->codeBlock(), STUB_RETURN_ADDRESS, baseValue, ident, slot);
+    CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
+    StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
+    if (!stubInfo->seenOnce())
+        stubInfo->setSeen();
+    else
+        JITThunks::tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo);
 
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
@@ -1227,7 +1386,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
         PolymorphicAccessStructureList* polymorphicStructureList;
         int listIndex = 1;
 
         PolymorphicAccessStructureList* polymorphicStructureList;
         int listIndex = 1;
 
-        if (stubInfo->opcodeID == op_get_by_id_self) {
+        if (stubInfo->accessType == access_get_by_id_self) {
             ASSERT(!stubInfo->stubRoutine);
             polymorphicStructureList = new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure);
             stubInfo->initGetByIdSelfList(polymorphicStructureList, 2);
             ASSERT(!stubInfo->stubRoutine);
             polymorphicStructureList = new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure);
             stubInfo->initGetByIdSelfList(polymorphicStructureList, 2);
@@ -1251,18 +1410,18 @@ static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(Str
     PolymorphicAccessStructureList* prototypeStructureList = 0;
     listIndex = 1;
 
     PolymorphicAccessStructureList* prototypeStructureList = 0;
     listIndex = 1;
 
-    switch (stubInfo->opcodeID) {
-    case op_get_by_id_proto:
+    switch (stubInfo->accessType) {
+    case access_get_by_id_proto:
         prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
         stubInfo->stubRoutine = CodeLocationLabel();
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
         prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
         stubInfo->stubRoutine = CodeLocationLabel();
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
-    case op_get_by_id_chain:
+    case access_get_by_id_chain:
         prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
         stubInfo->stubRoutine = CodeLocationLabel();
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
         prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
         stubInfo->stubRoutine = CodeLocationLabel();
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
-    case op_get_by_id_proto_list:
+    case access_get_by_id_proto_list:
         prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
         listIndex = stubInfo->u.getByIdProtoList.listSize;
         stubInfo->u.getByIdProtoList.listSize++;
         prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
         listIndex = stubInfo->u.getByIdProtoList.listSize;
         stubInfo->u.getByIdProtoList.listSize++;
@@ -1288,7 +1447,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
 
     CHECK_FOR_EXCEPTION();
 
 
     CHECK_FOR_EXCEPTION();
 
-    if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isUncacheableDictionary()) {
+    if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
         return JSValue::encode(result);
     }
         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
         return JSValue::encode(result);
     }
@@ -1305,6 +1464,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
     if (slot.slotBase() == baseValue)
         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
     else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) {
     if (slot.slotBase() == baseValue)
         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
     else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) {
+        ASSERT(!asCell(baseValue)->structure()->isDictionary());
         // Since we're accessing a prototype in a loop, it's a good bet that it
         // should not be treated as a dictionary.
         if (slotBaseObject->structure()->isDictionary()) {
         // Since we're accessing a prototype in a loop, it's a good bet that it
         // should not be treated as a dictionary.
         if (slotBaseObject->structure()->isDictionary()) {
@@ -1320,14 +1480,11 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
     } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
     } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
-        StructureChain* protoChain = structure->prototypeChain(callFrame);
-        if (!protoChain->isCacheable()) {
-            ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
-            return JSValue::encode(result);
-        }
-        
+        ASSERT(!asCell(baseValue)->structure()->isDictionary());
         int listIndex;
         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
         int listIndex;
         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
+
+        StructureChain* protoChain = structure->prototypeChain(callFrame);
         JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, offset);
 
         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
         JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, offset);
 
         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
@@ -1405,7 +1562,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
 
     // ECMA-262 15.3.5.3:
     // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
 
     // ECMA-262 15.3.5.3:
     // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
-    TypeInfo typeInfo(UnspecifiedType, 0);
+    TypeInfo typeInfo(UnspecifiedType);
     if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) {
         CallFrame* callFrame = stackFrame.callFrame;
         CodeBlock* codeBlock = callFrame->codeBlock();
     if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) {
         CallFrame* callFrame = stackFrame.callFrame;
         CodeBlock* codeBlock = callFrame->codeBlock();
@@ -1466,25 +1623,25 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    return stackFrame.args[0].funcDeclNode()->makeFunction(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
+    return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
 }
 
 DEFINE_STUB_FUNCTION(void*, op_call_JSFunction)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 }
 
 DEFINE_STUB_FUNCTION(void*, op_call_JSFunction)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-#ifndef NDEBUG
+#if !ASSERT_DISABLED
     CallData callData;
     ASSERT(stackFrame.args[0].jsValue().getCallData(callData) == CallTypeJS);
 #endif
 
     JSFunction* function = asFunction(stackFrame.args[0].jsValue());
     ASSERT(!function->isHostFunction());
     CallData callData;
     ASSERT(stackFrame.args[0].jsValue().getCallData(callData) == CallTypeJS);
 #endif
 
     JSFunction* function = asFunction(stackFrame.args[0].jsValue());
     ASSERT(!function->isHostFunction());
-    FunctionBodyNode* body = function->body();
+    FunctionExecutable* executable = function->jsExecutable();
     ScopeChainNode* callDataScopeChain = function->scope().node();
     ScopeChainNode* callDataScopeChain = function->scope().node();
-    body->jitCode(callDataScopeChain);
+    executable->jitCode(stackFrame.callFrame, callDataScopeChain);
 
 
-    return &(body->generatedBytecode());
+    return function;
 }
 
 DEFINE_STUB_FUNCTION(VoidPtrPair, op_call_arityCheck)
 }
 
 DEFINE_STUB_FUNCTION(VoidPtrPair, op_call_arityCheck)
@@ -1492,8 +1649,9 @@ DEFINE_STUB_FUNCTION(VoidPtrPair, op_call_arityCheck)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
-    CodeBlock* newCodeBlock = stackFrame.args[3].codeBlock();
-    ASSERT(newCodeBlock->codeType() != NativeCode);
+    JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
+    ASSERT(!callee->isHostFunction());
+    CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecode();
     int argCount = stackFrame.args[2].int32();
 
     ASSERT(argCount != newCodeBlock->m_numParameters);
     int argCount = stackFrame.args[2].int32();
 
     ASSERT(argCount != newCodeBlock->m_numParameters);
@@ -1530,37 +1688,26 @@ DEFINE_STUB_FUNCTION(VoidPtrPair, op_call_arityCheck)
         callFrame->setCallerFrame(oldCallFrame);
     }
 
         callFrame->setCallerFrame(oldCallFrame);
     }
 
-    RETURN_POINTER_PAIR(newCodeBlock, callFrame);
+    RETURN_POINTER_PAIR(callee, callFrame);
 }
 
 #if ENABLE(JIT_OPTIMIZE_CALL)
 }
 
 #if ENABLE(JIT_OPTIMIZE_CALL)
-DEFINE_STUB_FUNCTION(void*, vm_dontLazyLinkCall)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    JSGlobalData* globalData = stackFrame.globalData;
-    JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
-
-    ctiPatchNearCallByReturnAddress(stackFrame.callFrame->callerFrame()->codeBlock(), stackFrame.args[1].returnAddress(), globalData->jitStubs.ctiVirtualCallLink());
-
-    return callee->body()->generatedJITCode().addressForCall().executableAddress();
-}
-
 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
     JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
     JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
-    JITCode& jitCode = callee->body()->generatedJITCode();
+    ExecutableBase* executable = callee->executable();
+    JITCode& jitCode = executable->generatedJITCode();
     
     CodeBlock* codeBlock = 0;
     
     CodeBlock* codeBlock = 0;
-    if (!callee->isHostFunction())
-        codeBlock = &callee->body()->bytecode(callee->scope().node());
-    else
-        codeBlock = &callee->body()->generatedBytecode();
-
+    if (!executable->isHostFunction())
+        codeBlock = &static_cast<FunctionExecutable*>(executable)->bytecode(stackFrame.callFrame, callee->scope().node());
     CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress());
     CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress());
-    JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData);
+
+    if (!callLinkInfo->seenOnce())
+        callLinkInfo->setSeen();
+    else
+        JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData);
 
     return jitCode.addressForCall().executableAddress();
 }
 
     return jitCode.addressForCall().executableAddress();
 }
@@ -1570,7 +1717,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    JSActivation* activation = new (stackFrame.globalData) JSActivation(stackFrame.callFrame, static_cast<FunctionBodyNode*>(stackFrame.callFrame->codeBlock()->ownerNode()));
+    JSActivation* activation = new (stackFrame.globalData) JSActivation(stackFrame.callFrame, static_cast<FunctionExecutable*>(stackFrame.callFrame->codeBlock()->ownerExecutable()));
     stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->copy()->push(activation));
     return activation;
 }
     stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->copy()->push(activation));
     return activation;
 }
@@ -1732,7 +1879,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct)
         VM_THROW_EXCEPTION();
     }
 
         VM_THROW_EXCEPTION();
     }
 
-#ifndef NDEBUG
+#if !ASSERT_DISABLED
     ConstructData constructData;
     ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
 #endif
     ConstructData constructData;
     ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
 #endif
@@ -1741,7 +1888,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct)
     if (stackFrame.args[3].jsValue().isObject())
         structure = asObject(stackFrame.args[3].jsValue())->inheritorID();
     else
     if (stackFrame.args[3].jsValue().isObject())
         structure = asObject(stackFrame.args[3].jsValue())->inheritorID();
     else
-        structure = constructor->scope().node()->globalObject()->emptyObjectStructure();
+        structure = constructor->scope().node()->globalObject->emptyObjectStructure();
     return new (stackFrame.globalData) JSObject(structure);
 }
 
     return new (stackFrame.globalData) JSObject(structure);
 }
 
@@ -1802,7 +1949,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
         } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
         } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
-            result = asString(baseValue)->getIndex(stackFrame.globalData, i);
+            result = asString(baseValue)->getIndex(callFrame, i);
         } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
         } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
@@ -1833,7 +1980,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
     if (LIKELY(subscript.isUInt32())) {
         uint32_t i = subscript.asUInt32();
         if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
     if (LIKELY(subscript.isUInt32())) {
         uint32_t i = subscript.asUInt32();
         if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
-            result = asString(baseValue)->getIndex(stackFrame.globalData, i);
+            result = asString(baseValue)->getIndex(callFrame, i);
         else {
             result = baseValue.get(callFrame, i);
             if (!isJSString(globalData, baseValue))
         else {
             result = baseValue.get(callFrame, i);
             if (!isJSString(globalData, baseValue))
@@ -1945,28 +2092,6 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val)
     CHECK_FOR_EXCEPTION_AT_END();
 }
 
     CHECK_FOR_EXCEPTION_AT_END();
 }
 
-DEFINE_STUB_FUNCTION(void, op_put_by_val_array)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    CallFrame* callFrame = stackFrame.callFrame;
-    JSValue baseValue = stackFrame.args[0].jsValue();
-    int i = stackFrame.args[1].int32();
-    JSValue value = stackFrame.args[2].jsValue();
-
-    ASSERT(isJSArray(stackFrame.globalData, baseValue));
-
-    if (LIKELY(i >= 0))
-        asArray(baseValue)->JSArray::put(callFrame, i, value);
-    else {
-        Identifier property(callFrame, UString::from(i));
-        PutPropertySlot slot;
-        baseValue.put(callFrame, property, value, slot);
-    }
-
-    CHECK_FOR_EXCEPTION_AT_END();
-}
-
 DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -2020,19 +2145,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
     return JSValue::encode(result);
 }
 
     return JSValue::encode(result);
 }
 
-DEFINE_STUB_FUNCTION(int, op_loop_if_true)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    JSValue src1 = stackFrame.args[0].jsValue();
-
-    CallFrame* callFrame = stackFrame.callFrame;
-
-    bool result = src1.toBoolean(callFrame);
-    CHECK_FOR_EXCEPTION_AT_END();
-    return result;
-}
-    
 DEFINE_STUB_FUNCTION(int, op_load_varargs)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(int, op_load_varargs)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -2051,7 +2163,7 @@ DEFINE_STUB_FUNCTION(int, op_load_varargs)
             stackFrame.globalData->exception = createStackOverflowError(callFrame);
             VM_THROW_EXCEPTION();
         }
             stackFrame.globalData->exception = createStackOverflowError(callFrame);
             VM_THROW_EXCEPTION();
         }
-        int32_t expectedParams = callFrame->callee()->body()->parameterCount();
+        int32_t expectedParams = callFrame->callee()->jsExecutable()->parameterCount();
         int32_t inplaceArgs = min(providedParams, expectedParams);
         
         Register* inplaceArgsDst = callFrame->registers() + argsOffset;
         int32_t inplaceArgs = min(providedParams, expectedParams);
         
         Register* inplaceArgsDst = callFrame->registers() + argsOffset;
@@ -2307,8 +2419,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_inc)
     return JSValue::encode(number);
 }
 
     return JSValue::encode(number);
 }
 
-#if USE(JSVALUE32_64)
-
 DEFINE_STUB_FUNCTION(int, op_eq)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(int, op_eq)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -2316,6 +2426,7 @@ DEFINE_STUB_FUNCTION(int, op_eq)
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
+#if USE(JSVALUE32_64)
     start:
     if (src2.isUndefined()) {
         return src1.isNull() || 
     start:
     if (src2.isUndefined()) {
         return src1.isNull() || 
@@ -2367,42 +2478,47 @@ DEFINE_STUB_FUNCTION(int, op_eq)
     if (src1.isNull())
         return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined();
 
     if (src1.isNull())
         return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined();
 
-    ASSERT(src1.isCell());
-
     JSCell* cell1 = asCell(src1);
 
     if (cell1->isString()) {
         if (src2.isInt32())
     JSCell* cell1 = asCell(src1);
 
     if (cell1->isString()) {
         if (src2.isInt32())
-            return static_cast<JSString*>(cell1)->value().toDouble() == src2.asInt32();
+            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asInt32();
             
         if (src2.isDouble())
             
         if (src2.isDouble())
-            return static_cast<JSString*>(cell1)->value().toDouble() == src2.asDouble();
+            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asDouble();
 
         if (src2.isTrue())
 
         if (src2.isTrue())
-            return static_cast<JSString*>(cell1)->value().toDouble() == 1.0;
+            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 1.0;
 
         if (src2.isFalse())
 
         if (src2.isFalse())
-            return static_cast<JSString*>(cell1)->value().toDouble() == 0.0;
+            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 0.0;
 
 
-        ASSERT(src2.isCell());
         JSCell* cell2 = asCell(src2);
         if (cell2->isString())
         JSCell* cell2 = asCell(src2);
         if (cell2->isString())
-            return static_cast<JSString*>(cell1)->value() == static_cast<JSString*>(cell2)->value();
+            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame) == static_cast<JSString*>(cell2)->value(stackFrame.callFrame);
 
 
-        ASSERT(cell2->isObject());
-        src2 = static_cast<JSObject*>(cell2)->toPrimitive(stackFrame.callFrame);
+        src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
         CHECK_FOR_EXCEPTION();
         goto start;
     }
 
         CHECK_FOR_EXCEPTION();
         goto start;
     }
 
-    ASSERT(cell1->isObject());
     if (src2.isObject())
     if (src2.isObject())
-        return static_cast<JSObject*>(cell1) == asObject(src2);
-    src1 = static_cast<JSObject*>(cell1)->toPrimitive(stackFrame.callFrame);
+        return asObject(cell1) == asObject(src2);
+    src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame);
     CHECK_FOR_EXCEPTION();
     goto start;
     CHECK_FOR_EXCEPTION();
     goto start;
+    
+#else // USE(JSVALUE32_64)
+    CallFrame* callFrame = stackFrame.callFrame;
+    
+    bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2);
+    CHECK_FOR_EXCEPTION_AT_END();
+    return result;
+#endif // USE(JSVALUE32_64)
 }
 
 }
 
+#if USE(JSVALUE32_64)
+
 DEFINE_STUB_FUNCTION(int, op_eq_strings)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(int, op_eq_strings)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -2412,26 +2528,10 @@ DEFINE_STUB_FUNCTION(int, op_eq_strings)
 
     ASSERT(string1->isString());
     ASSERT(string2->isString());
 
     ASSERT(string1->isString());
     ASSERT(string2->isString());
-    return string1->value() == string2->value();
-}
-
-#else // USE(JSVALUE32_64)
-
-DEFINE_STUB_FUNCTION(int, op_eq)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    JSValue src1 = stackFrame.args[0].jsValue();
-    JSValue src2 = stackFrame.args[1].jsValue();
-
-    CallFrame* callFrame = stackFrame.callFrame;
-
-    bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2);
-    CHECK_FOR_EXCEPTION_AT_END();
-    return result;
+    return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame);
 }
 
 }
 
-#endif // USE(JSVALUE32_64)
+#endif
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift)
 {
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift)
 {
@@ -2526,8 +2626,24 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base)
 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
+    CallFrame* callFrame = stackFrame.callFrame;
 
 
-    return stackFrame.args[0].funcExprNode()->makeFunction(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
+    FunctionExecutable* function = stackFrame.args[0].function();
+    JSFunction* func = function->make(callFrame, callFrame->scopeChain());
+
+    /* 
+        The Identifier in a FunctionExpression can be referenced from inside
+        the FunctionExpression's FunctionBody to allow the function to call
+        itself recursively. However, unlike in a FunctionDeclaration, the
+        Identifier in a FunctionExpression cannot be referenced from and
+        does not affect the scope enclosing the FunctionExpression.
+     */
+    if (!function->name().isNull()) {
+        JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
+        func->scope().push(functionScopeObject);
+    }
+
+    return func;
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod)
@@ -2633,7 +2749,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
     Register* newCallFrame = callFrame->registers() + registerOffset;
     Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
     JSValue thisValue = argv[0].jsValue();
     Register* newCallFrame = callFrame->registers() + registerOffset;
     Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
     JSValue thisValue = argv[0].jsValue();
-    JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
+    JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
 
     if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
         JSValue exceptionValue;
 
     if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
         JSValue exceptionValue;
@@ -2664,7 +2780,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_throw)
 
     if (!handler) {
         *stackFrame.exception = exceptionValue;
 
     if (!handler) {
         *stackFrame.exception = exceptionValue;
-        STUB_SET_RETURN_ADDRESS(reinterpret_cast<void*>(ctiOpThrowNotCaught));
+        STUB_SET_RETURN_ADDRESS(FunctionPtr(ctiOpThrowNotCaught).value());
         return JSValue::encode(jsNull());
     }
 
         return JSValue::encode(jsNull());
     }
 
@@ -2679,18 +2795,22 @@ DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    return JSPropertyNameIterator::create(stackFrame.callFrame, stackFrame.args[0].jsValue());
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSObject* o = stackFrame.args[0].jsObject();
+    Structure* structure = o->structure();
+    JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
+    if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
+        jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
+    return jsPropertyNameIterator;
 }
 
 }
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_next_pname)
+DEFINE_STUB_FUNCTION(int, has_property)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    JSPropertyNameIterator* it = stackFrame.args[0].propertyNameIterator();
-    JSValue temp = it->next(stackFrame.callFrame);
-    if (!temp)
-        it->invalidate();
-    return JSValue::encode(temp);
+    JSObject* base = stackFrame.args[0].jsObject();
+    JSString* property = stackFrame.args[1].jsString();
+    return base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame)));
 }
 
 DEFINE_STUB_FUNCTION(JSObject*, op_push_scope)
 }
 
 DEFINE_STUB_FUNCTION(JSObject*, op_push_scope)
@@ -2767,7 +2887,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq)
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
-    return JSValue::encode(jsBoolean(JSValue::strictEqual(src1, src2)));
+    return JSValue::encode(jsBoolean(JSValue::strictEqual(stackFrame.callFrame, src1, src2)));
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive)
@@ -2781,7 +2901,9 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    return JSValue::encode(concatenateStrings(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32()));
+    JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
+    CHECK_FOR_EXCEPTION_AT_END();
+    return JSValue::encode(result);
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq)
@@ -2791,7 +2913,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq)
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
-    return JSValue::encode(jsBoolean(!JSValue::strictEqual(src1, src2)));
+    return JSValue::encode(jsBoolean(!JSValue::strictEqual(stackFrame.callFrame, src1, src2)));
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber)
@@ -2900,7 +3022,7 @@ DEFINE_STUB_FUNCTION(void*, op_switch_char)
     void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
 
     if (scrutinee.isString()) {
     void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
 
     if (scrutinee.isString()) {
-        UString::Rep* value = asString(scrutinee)->value().rep();
+        UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
         if (value->size() == 1)
             result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]).executableAddress();
     }
         if (value->size() == 1)
             result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]).executableAddress();
     }
@@ -2920,7 +3042,7 @@ DEFINE_STUB_FUNCTION(void*, op_switch_string)
     void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
 
     if (scrutinee.isString()) {
     void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
 
     if (scrutinee.isString()) {
-        UString::Rep* value = asString(scrutinee)->value().rep();
+        UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
         result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
     }
 
         result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
     }
 
@@ -2987,7 +3109,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_error)
     unsigned bytecodeOffset = stackFrame.args[2].int32();
 
     unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
     unsigned bytecodeOffset = stackFrame.args[2].int32();
 
     unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
-    return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+    return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
 }
 
 DEFINE_STUB_FUNCTION(void, op_debug)
 }
 
 DEFINE_STUB_FUNCTION(void, op_debug)
@@ -3031,6 +3153,14 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, vm_throw)
     return JSValue::encode(exceptionValue);
 }
 
     return JSValue::encode(exceptionValue);
 }
 
+DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+    CallFrame* callFrame = stackFrame.callFrame;
+    return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
+}
+
 } // namespace JSC
 
 #endif // ENABLE(JIT)
 } // namespace JSC
 
 #endif // ENABLE(JIT)
index 317eca98378a5da6962827ad016fbd68bac734f2..99c2dd2b7ea9e0bf85f70f679a2e1723b5b4ff3e 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
+    struct StructureStubInfo;
+
     class CodeBlock;
     class ExecutablePool;
     class CodeBlock;
     class ExecutablePool;
+    class FunctionExecutable;
     class Identifier;
     class JSGlobalData;
     class JSGlobalData;
     class Identifier;
     class JSGlobalData;
     class JSGlobalData;
@@ -51,8 +54,6 @@ namespace JSC {
     class PropertySlot;
     class PutPropertySlot;
     class RegisterFile;
     class PropertySlot;
     class PutPropertySlot;
     class RegisterFile;
-    class FuncDeclNode;
-    class FuncExprNode;
     class JSGlobalObject;
     class RegExp;
 
     class JSGlobalObject;
     class RegExp;
 
@@ -62,11 +63,11 @@ namespace JSC {
         int32_t asInt32;
 
         JSValue jsValue() { return JSValue::decode(asEncodedJSValue); }
         int32_t asInt32;
 
         JSValue jsValue() { return JSValue::decode(asEncodedJSValue); }
+        JSObject* jsObject() { return static_cast<JSObject*>(asPointer); }
         Identifier& identifier() { return *static_cast<Identifier*>(asPointer); }
         int32_t int32() { return asInt32; }
         CodeBlock* codeBlock() { return static_cast<CodeBlock*>(asPointer); }
         Identifier& identifier() { return *static_cast<Identifier*>(asPointer); }
         int32_t int32() { return asInt32; }
         CodeBlock* codeBlock() { return static_cast<CodeBlock*>(asPointer); }
-        FuncDeclNode* funcDeclNode() { return static_cast<FuncDeclNode*>(asPointer); }
-        FuncExprNode* funcExprNode() { return static_cast<FuncExprNode*>(asPointer); }
+        FunctionExecutable* function() { return static_cast<FunctionExecutable*>(asPointer); }
         RegExp* regExp() { return static_cast<RegExp*>(asPointer); }
         JSPropertyNameIterator* propertyNameIterator() { return static_cast<JSPropertyNameIterator*>(asPointer); }
         JSGlobalObject* globalObject() { return static_cast<JSGlobalObject*>(asPointer); }
         RegExp* regExp() { return static_cast<RegExp*>(asPointer); }
         JSPropertyNameIterator* propertyNameIterator() { return static_cast<JSPropertyNameIterator*>(asPointer); }
         JSGlobalObject* globalObject() { return static_cast<JSGlobalObject*>(asPointer); }
@@ -74,12 +75,19 @@ namespace JSC {
         ReturnAddressPtr returnAddress() { return ReturnAddressPtr(asPointer); }
     };
 
         ReturnAddressPtr returnAddress() { return ReturnAddressPtr(asPointer); }
     };
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     struct JITStackFrame {
         void* reserved; // Unused
         JITStubArg args[6];
         void* padding[2]; // Maintain 32-byte stack alignment (possibly overkill).
 
     struct JITStackFrame {
         void* reserved; // Unused
         JITStubArg args[6];
         void* padding[2]; // Maintain 32-byte stack alignment (possibly overkill).
 
+        void* code;
+        RegisterFile* registerFile;
+        CallFrame* callFrame;
+        JSValue* exception;
+        Profiler** enabledProfilerReference;
+        JSGlobalData* globalData;
+
         void* savedRBX;
         void* savedR15;
         void* savedR14;
         void* savedRBX;
         void* savedR15;
         void* savedR14;
@@ -88,17 +96,10 @@ namespace JSC {
         void* savedRBP;
         void* savedRIP;
 
         void* savedRBP;
         void* savedRIP;
 
-        void* code;
-        RegisterFile* registerFile;
-        CallFrame* callFrame;
-        JSValue* exception;
-        Profiler** enabledProfilerReference;
-        JSGlobalData* globalData;
-
         // When JIT code makes a call, it pushes its return address just below the rest of the stack.
         ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast<ReturnAddressPtr*>(this) - 1; }
     };
         // When JIT code makes a call, it pushes its return address just below the rest of the stack.
         ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast<ReturnAddressPtr*>(this) - 1; }
     };
-#elif PLATFORM(X86)
+#elif CPU(X86)
 #if COMPILER(MSVC)
 #pragma pack(push)
 #pragma pack(4)
 #if COMPILER(MSVC)
 #pragma pack(push)
 #pragma pack(4)
@@ -129,7 +130,7 @@ namespace JSC {
 #if COMPILER(MSVC)
 #pragma pack(pop)
 #endif // COMPILER(MSVC)
 #if COMPILER(MSVC)
 #pragma pack(pop)
 #endif // COMPILER(MSVC)
-#elif PLATFORM_ARM_ARCH(7)
+#elif CPU(ARM_THUMB2)
     struct JITStackFrame {
         void* reserved; // Unused
         JITStubArg args[6];
     struct JITStackFrame {
         void* reserved; // Unused
         JITStubArg args[6];
@@ -149,16 +150,45 @@ namespace JSC {
         CallFrame* callFrame;
         JSValue* exception;
 
         CallFrame* callFrame;
         JSValue* exception;
 
+        void* padding2;
+
         // These arguments passed on the stack.
         Profiler** enabledProfilerReference;
         JSGlobalData* globalData;
         
         // These arguments passed on the stack.
         Profiler** enabledProfilerReference;
         JSGlobalData* globalData;
         
+        ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
+    };
+#elif CPU(ARM_TRADITIONAL)
+    struct JITStackFrame {
+        JITStubArg padding; // Unused
+        JITStubArg args[7];
+
+        ReturnAddressPtr thunkReturnAddress;
+
+        void* preservedR4;
+        void* preservedR5;
+        void* preservedR6;
+        void* preservedR7;
+        void* preservedR8;
+        void* preservedLink;
+
+        RegisterFile* registerFile;
+        CallFrame* callFrame;
+        JSValue* exception;
+
+        // These arguments passed on the stack.
+        Profiler** enabledProfilerReference;
+        JSGlobalData* globalData;
+
+        // When JIT code makes a call, it pushes its return address just below the rest of the stack.
         ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
     };
 #else
 #error "JITStackFrame not defined for this platform."
 #endif
 
         ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
     };
 #else
 #error "JITStackFrame not defined for this platform."
 #endif
 
+#define JITSTACKFRAME_ARGS_INDEX (OBJECT_OFFSETOF(JITStackFrame, args) / sizeof(void*))
+
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
     #define STUB_ARGS_DECLARATION void* args, ...
     #define STUB_ARGS (reinterpret_cast<void**>(vl_args) - 1)
 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
     #define STUB_ARGS_DECLARATION void* args, ...
     #define STUB_ARGS (reinterpret_cast<void**>(vl_args) - 1)
@@ -172,16 +202,16 @@ namespace JSC {
     #define STUB_ARGS_DECLARATION void** args
     #define STUB_ARGS (args)
 
     #define STUB_ARGS_DECLARATION void** args
     #define STUB_ARGS (args)
 
-    #if PLATFORM(X86) && COMPILER(MSVC)
+    #if CPU(X86) && COMPILER(MSVC)
     #define JIT_STUB __fastcall
     #define JIT_STUB __fastcall
-    #elif PLATFORM(X86) && COMPILER(GCC)
+    #elif CPU(X86) && COMPILER(GCC)
     #define JIT_STUB  __attribute__ ((fastcall))
     #else
     #define JIT_STUB
     #endif
 #endif
 
     #define JIT_STUB  __attribute__ ((fastcall))
     #else
     #define JIT_STUB
     #endif
 #endif
 
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
     struct VoidPtrPair {
         void* first;
         void* second;
     struct VoidPtrPair {
         void* first;
         void* second;
@@ -200,23 +230,16 @@ namespace JSC {
 
     extern "C" void ctiVMThrowTrampoline();
     extern "C" void ctiOpThrowNotCaught();
 
     extern "C" void ctiVMThrowTrampoline();
     extern "C" void ctiOpThrowNotCaught();
-    extern "C" EncodedJSValue ctiTrampoline(
-#if PLATFORM(X86_64)
-            // FIXME: (bug #22910) this will force all arguments onto the stack (regparm(0) does not appear to have any effect).
-            // We can allow register passing here, and move the writes of these values into the trampoline.
-            void*, void*, void*, void*, void*, void*,
-#endif
-            void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*);
+    extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*);
 
     class JITThunks {
     public:
         JITThunks(JSGlobalData*);
 
 
     class JITThunks {
     public:
         JITThunks(JSGlobalData*);
 
-        static void tryCacheGetByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot&);
-        static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&);
-        
+        static void tryCacheGetByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot&, StructureStubInfo* stubInfo);
+        static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&, StructureStubInfo* stubInfo);
+
         MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_ctiStringLengthTrampoline; }
         MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_ctiStringLengthTrampoline; }
-        MacroAssemblerCodePtr ctiVirtualCallPreLink() { return m_ctiVirtualCallPreLink; }
         MacroAssemblerCodePtr ctiVirtualCallLink() { return m_ctiVirtualCallLink; }
         MacroAssemblerCodePtr ctiVirtualCall() { return m_ctiVirtualCall; }
         MacroAssemblerCodePtr ctiNativeCallThunk() { return m_ctiNativeCallThunk; }
         MacroAssemblerCodePtr ctiVirtualCallLink() { return m_ctiVirtualCallLink; }
         MacroAssemblerCodePtr ctiVirtualCall() { return m_ctiVirtualCall; }
         MacroAssemblerCodePtr ctiNativeCallThunk() { return m_ctiNativeCallThunk; }
@@ -225,7 +248,6 @@ namespace JSC {
         RefPtr<ExecutablePool> m_executablePool;
 
         MacroAssemblerCodePtr m_ctiStringLengthTrampoline;
         RefPtr<ExecutablePool> m_executablePool;
 
         MacroAssemblerCodePtr m_ctiStringLengthTrampoline;
-        MacroAssemblerCodePtr m_ctiVirtualCallPreLink;
         MacroAssemblerCodePtr m_ctiVirtualCallLink;
         MacroAssemblerCodePtr m_ctiVirtualCall;
         MacroAssemblerCodePtr m_ctiNativeCallThunk;
         MacroAssemblerCodePtr m_ctiVirtualCallLink;
         MacroAssemblerCodePtr m_ctiVirtualCall;
         MacroAssemblerCodePtr m_ctiNativeCallThunk;
@@ -248,11 +270,9 @@ extern "C" {
     EncodedJSValue JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_generic(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_generic(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION);
-    EncodedJSValue JIT_STUB cti_op_get_by_id_method_check_second(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION);
-    EncodedJSValue JIT_STUB cti_op_get_by_id_second(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_val(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_val(STUB_ARGS_DECLARATION);
@@ -272,7 +292,6 @@ extern "C" {
     EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_negate(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_negate(STUB_ARGS_DECLARATION);
-    EncodedJSValue JIT_STUB cti_op_next_pname(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_not(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_nstricteq(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_post_dec(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_not(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_nstricteq(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_post_dec(STUB_ARGS_DECLARATION);
@@ -294,6 +313,7 @@ extern "C" {
     EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_to_object(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_construct_JSConstruct(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_new_error(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_construct_JSConstruct(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_new_error(STUB_ARGS_DECLARATION);
@@ -315,10 +335,9 @@ extern "C" {
     int JIT_STUB cti_op_jlesseq(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_jlesseq(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION);
-    int JIT_STUB cti_op_loop_if_less(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION);
-    int JIT_STUB cti_op_loop_if_true(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION);
+    int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION);
@@ -330,10 +349,8 @@ extern "C" {
     void JIT_STUB cti_op_put_by_id(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_id(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION);
-    void JIT_STUB cti_op_put_by_id_second(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION);
-    void JIT_STUB cti_op_put_by_val_array(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_getter(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_setter(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_getter(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_setter(STUB_ARGS_DECLARATION);
@@ -345,7 +362,6 @@ extern "C" {
     void* JIT_STUB cti_op_switch_char(STUB_ARGS_DECLARATION);
     void* JIT_STUB cti_op_switch_imm(STUB_ARGS_DECLARATION);
     void* JIT_STUB cti_op_switch_string(STUB_ARGS_DECLARATION);
     void* JIT_STUB cti_op_switch_char(STUB_ARGS_DECLARATION);
     void* JIT_STUB cti_op_switch_imm(STUB_ARGS_DECLARATION);
     void* JIT_STUB cti_op_switch_string(STUB_ARGS_DECLARATION);
-    void* JIT_STUB cti_vm_dontLazyLinkCall(STUB_ARGS_DECLARATION);
     void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION);
 } // extern "C"
 
     void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION);
 } // extern "C"
 
diff --git a/jsc.cpp b/jsc.cpp
index efe3fa5e836d160288b2c4952ae4a15c06d4f1f3..252fb961c98cfc125870ddc730bd3fb3fbf5c046 100644 (file)
--- a/jsc.cpp
+++ b/jsc.cpp
 
 #include "BytecodeGenerator.h"
 #include "Completion.h"
 
 #include "BytecodeGenerator.h"
 #include "Completion.h"
+#include "CurrentTime.h"
 #include "InitializeThreading.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JSLock.h"
 #include "InitializeThreading.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JSLock.h"
+#include "JSString.h"
 #include "PrototypeFunction.h"
 #include "SamplingTool.h"
 #include <math.h>
 #include "PrototypeFunction.h"
 #include "SamplingTool.h"
 #include <math.h>
@@ -35,7 +37,7 @@
 #include <stdlib.h>
 #include <string.h>
 
 #include <stdlib.h>
 #include <string.h>
 
-#if !PLATFORM(WIN_OS)
+#if !OS(WINDOWS)
 #include <unistd.h>
 #endif
 
 #include <unistd.h>
 #endif
 
 #include <signal.h>
 #endif
 
 #include <signal.h>
 #endif
 
-#if COMPILER(MSVC) && !PLATFORM(WINCE)
+#if COMPILER(MSVC) && !OS(WINCE)
 #include <crtdbg.h>
 #include <crtdbg.h>
-#include <windows.h>
 #include <mmsystem.h>
 #include <mmsystem.h>
+#include <windows.h>
 #endif
 
 #if PLATFORM(QT)
 #endif
 
 #if PLATFORM(QT)
@@ -86,8 +88,8 @@ static JSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*, JSObject*, J
 
 struct Script {
     bool isFile;
 
 struct Script {
     bool isFile;
-    char *argument;
-    
+    charargument;
+
     Script(bool isFile, char *argument)
         : isFile(isFile)
         , argument(argument)
     Script(bool isFile, char *argument)
         : isFile(isFile)
         , argument(argument)
@@ -118,53 +120,23 @@ public:
     long getElapsedMS(); // call stop() first
 
 private:
     long getElapsedMS(); // call stop() first
 
 private:
-#if PLATFORM(QT)
-    uint m_startTime;
-    uint m_stopTime;
-#elif PLATFORM(WIN_OS)
-    DWORD m_startTime;
-    DWORD m_stopTime;
-#else
-    // Windows does not have timeval, disabling this class for now (bug 7399)
-    timeval m_startTime;
-    timeval m_stopTime;
-#endif
+    double m_startTime;
+    double m_stopTime;
 };
 
 void StopWatch::start()
 {
 };
 
 void StopWatch::start()
 {
-#if PLATFORM(QT)
-    QDateTime t = QDateTime::currentDateTime();
-    m_startTime = t.toTime_t() * 1000 + t.time().msec();
-#elif PLATFORM(WIN_OS)
-    m_startTime = timeGetTime();
-#else
-    gettimeofday(&m_startTime, 0);
-#endif
+    m_startTime = currentTime();
 }
 
 void StopWatch::stop()
 {
 }
 
 void StopWatch::stop()
 {
-#if PLATFORM(QT)
-    QDateTime t = QDateTime::currentDateTime();
-    m_stopTime = t.toTime_t() * 1000 + t.time().msec();
-#elif PLATFORM(WIN_OS)
-    m_stopTime = timeGetTime();
-#else
-    gettimeofday(&m_stopTime, 0);
-#endif
+    m_stopTime = currentTime();
 }
 
 long StopWatch::getElapsedMS()
 {
 }
 
 long StopWatch::getElapsedMS()
 {
-#if PLATFORM(WIN_OS) || PLATFORM(QT)
-    return m_stopTime - m_startTime;
-#else
-    timeval elapsedTime;
-    timersub(&m_stopTime, &m_startTime, &elapsedTime);
-
-    return elapsedTime.tv_sec * 1000 + lroundf(elapsedTime.tv_usec / 1000.0f);
-#endif
+    return static_cast<long>((m_stopTime - m_startTime) * 1000);
 }
 
 class GlobalObject : public JSGlobalObject {
 }
 
 class GlobalObject : public JSGlobalObject {
@@ -202,12 +174,12 @@ GlobalObject::GlobalObject(const Vector<UString>& arguments)
 JSValue JSC_HOST_CALL functionPrint(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
     for (unsigned i = 0; i < args.size(); ++i) {
 JSValue JSC_HOST_CALL functionPrint(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
     for (unsigned i = 0; i < args.size(); ++i) {
-        if (i != 0)
+        if (i)
             putchar(' ');
             putchar(' ');
-        
+
         printf("%s", args.at(i).toString(exec).UTF8String().c_str());
     }
         printf("%s", args.at(i).toString(exec).UTF8String().c_str());
     }
-    
+
     putchar('\n');
     fflush(stdout);
     return jsUndefined();
     putchar('\n');
     fflush(stdout);
     return jsUndefined();
@@ -221,8 +193,8 @@ JSValue JSC_HOST_CALL functionDebug(ExecState* exec, JSObject*, JSValue, const A
 
 JSValue JSC_HOST_CALL functionGC(ExecState* exec, JSObject*, JSValue, const ArgList&)
 {
 
 JSValue JSC_HOST_CALL functionGC(ExecState* exec, JSObject*, JSValue, const ArgList&)
 {
-    JSLock lock(false);
-    exec->heap()->collect();
+    JSLock lock(SilenceAssertionsOnly);
+    exec->heap()->collectAllGarbage();
     return jsUndefined();
 }
 
     return jsUndefined();
 }
 
@@ -320,8 +292,18 @@ JSValue JSC_HOST_CALL functionReadline(ExecState* exec, JSObject*, JSValue, cons
 
 JSValue JSC_HOST_CALL functionQuit(ExecState* exec, JSObject*, JSValue, const ArgList&)
 {
 
 JSValue JSC_HOST_CALL functionQuit(ExecState* exec, JSObject*, JSValue, const ArgList&)
 {
+    // Technically, destroying the heap in the middle of JS execution is a no-no,
+    // but we want to maintain compatibility with the Mozilla test suite, so
+    // we pretend that execution has terminated to avoid ASSERTs, then tear down the heap.
+    exec->globalData().dynamicGlobalObject = 0;
+
     cleanupGlobalData(&exec->globalData());
     exit(EXIT_SUCCESS);
     cleanupGlobalData(&exec->globalData());
     exit(EXIT_SUCCESS);
+
+#if COMPILER(MSVC) && OS(WINCE)
+    // Without this, Visual Studio will complain that this method does not return a value.
+    return jsUndefined();
+#endif
 }
 
 // Use SEH for Release builds only to get rid of the crash report dialog
 }
 
 // Use SEH for Release builds only to get rid of the crash report dialog
@@ -341,7 +323,7 @@ int jscmain(int argc, char** argv, JSGlobalData*);
 
 int main(int argc, char** argv)
 {
 
 int main(int argc, char** argv)
 {
-#if defined(_DEBUG) && PLATFORM(WIN_OS)
+#if defined(_DEBUG) && OS(WINDOWS)
     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
@@ -350,7 +332,7 @@ int main(int argc, char** argv)
     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
 #endif
 
     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
 #endif
 
-#if COMPILER(MSVC) && !PLATFORM(WINCE)
+#if COMPILER(MSVC) && !OS(WINCE)
     timeBeginPeriod(1);
 #endif
 
     timeBeginPeriod(1);
 #endif
 
@@ -375,7 +357,7 @@ int main(int argc, char** argv)
 
 static void cleanupGlobalData(JSGlobalData* globalData)
 {
 
 static void cleanupGlobalData(JSGlobalData* globalData)
 {
-    JSLock lock(false);
+    JSLock lock(SilenceAssertionsOnly);
     globalData->heap.destroy();
     globalData->deref();
 }
     globalData->heap.destroy();
     globalData->deref();
 }
@@ -389,11 +371,8 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
     if (dump)
         BytecodeGenerator::setDumpsGeneratedCode(true);
 
     if (dump)
         BytecodeGenerator::setDumpsGeneratedCode(true);
 
-#if ENABLE(OPCODE_SAMPLING)
-    Interpreter* interpreter = globalObject->globalData()->interpreter;
-    interpreter->setSampler(new SamplingTool(interpreter));
-    interpreter->sampler()->setup();
-#endif
+    JSGlobalData* globalData = globalObject->globalData();
+
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::start();
 #endif
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::start();
 #endif
@@ -410,9 +389,7 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
             fileName = "[Command Line]";
         }
 
             fileName = "[Command Line]";
         }
 
-#if ENABLE(SAMPLING_THREAD)
-        SamplingThread::start();
-#endif
+        globalData->startSampling();
 
         Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script, fileName));
         success = success && completion.complType() != Throw;
 
         Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script, fileName));
         success = success && completion.complType() != Throw;
@@ -423,20 +400,14 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
                 printf("End: %s\n", completion.value().toString(globalObject->globalExec()).ascii());
         }
 
                 printf("End: %s\n", completion.value().toString(globalObject->globalExec()).ascii());
         }
 
-#if ENABLE(SAMPLING_THREAD)
-        SamplingThread::stop();
-#endif
-
+        globalData->stopSampling();
         globalObject->globalExec()->clearException();
     }
 
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::stop();
 #endif
         globalObject->globalExec()->clearException();
     }
 
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::stop();
 #endif
-#if ENABLE(OPCODE_SAMPLING)
-    interpreter->sampler()->dump(globalObject->globalExec());
-    delete interpreter->sampler();
-#endif
+    globalData->dumpSampleData(globalObject->globalExec());
 #if ENABLE(SAMPLING_COUNTERS)
     AbstractSamplingCounter::dump();
 #endif
 #if ENABLE(SAMPLING_COUNTERS)
     AbstractSamplingCounter::dump();
 #endif
@@ -502,30 +473,27 @@ static void parseArguments(int argc, char** argv, Options& options, JSGlobalData
     int i = 1;
     for (; i < argc; ++i) {
         const char* arg = argv[i];
     int i = 1;
     for (; i < argc; ++i) {
         const char* arg = argv[i];
-        if (strcmp(arg, "-f") == 0) {
+        if (!strcmp(arg, "-f")) {
             if (++i == argc)
                 printUsageStatement(globalData);
             options.scripts.append(Script(true, argv[i]));
             continue;
         }
             if (++i == argc)
                 printUsageStatement(globalData);
             options.scripts.append(Script(true, argv[i]));
             continue;
         }
-        if (strcmp(arg, "-e") == 0) {
+        if (!strcmp(arg, "-e")) {
             if (++i == argc)
                 printUsageStatement(globalData);
             options.scripts.append(Script(false, argv[i]));
             continue;
         }
             if (++i == argc)
                 printUsageStatement(globalData);
             options.scripts.append(Script(false, argv[i]));
             continue;
         }
-        if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
-            printUsageStatement(globalData, true);
-        }
-        if (strcmp(arg, "-i") == 0) {
+        if (!strcmp(arg, "-i")) {
             options.interactive = true;
             continue;
         }
             options.interactive = true;
             continue;
         }
-        if (strcmp(arg, "-d") == 0) {
+        if (!strcmp(arg, "-d")) {
             options.dump = true;
             continue;
         }
             options.dump = true;
             continue;
         }
-        if (strcmp(arg, "-s") == 0) {
+        if (!strcmp(arg, "-s")) {
 #if HAVE(SIGNAL_H)
             signal(SIGILL, _exit);
             signal(SIGFPE, _exit);
 #if HAVE(SIGNAL_H)
             signal(SIGILL, _exit);
             signal(SIGFPE, _exit);
@@ -534,23 +502,25 @@ static void parseArguments(int argc, char** argv, Options& options, JSGlobalData
 #endif
             continue;
         }
 #endif
             continue;
         }
-        if (strcmp(arg, "--") == 0) {
+        if (!strcmp(arg, "--")) {
             ++i;
             break;
         }
             ++i;
             break;
         }
+        if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
+            printUsageStatement(globalData, true);
         options.scripts.append(Script(true, argv[i]));
     }
         options.scripts.append(Script(true, argv[i]));
     }
-    
+
     if (options.scripts.isEmpty())
         options.interactive = true;
     if (options.scripts.isEmpty())
         options.interactive = true;
-    
+
     for (; i < argc; ++i)
         options.arguments.append(argv[i]);
 }
 
 int jscmain(int argc, char** argv, JSGlobalData* globalData)
 {
     for (; i < argc; ++i)
         options.arguments.append(argv[i]);
 }
 
 int jscmain(int argc, char** argv, JSGlobalData* globalData)
 {
-    JSLock lock(false);
+    JSLock lock(SilenceAssertionsOnly);
 
     Options options;
     parseArguments(argc, argv, options, globalData);
 
     Options options;
     parseArguments(argc, argv, options, globalData);
@@ -571,20 +541,20 @@ static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>&
         return false;
     }
 
         return false;
     }
 
-    size_t buffer_size = 0;
-    size_t buffer_capacity = 1024;
+    size_t bufferSize = 0;
+    size_t bufferCapacity = 1024;
 
 
-    buffer.resize(buffer_capacity);
+    buffer.resize(bufferCapacity);
 
     while (!feof(f) && !ferror(f)) {
 
     while (!feof(f) && !ferror(f)) {
-        buffer_size += fread(buffer.data() + buffer_size, 1, buffer_capacity - buffer_size, f);
-        if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0'
-            buffer_capacity *= 2;
-            buffer.resize(buffer_capacity);
+        bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
+        if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
+            bufferCapacity *= 2;
+            buffer.resize(bufferCapacity);
         }
     }
     fclose(f);
         }
     }
     fclose(f);
-    buffer[buffer_size] = '\0';
+    buffer[bufferSize] = '\0';
 
     return true;
 }
 
     return true;
 }
diff --git a/jsc.pro b/jsc.pro
index 35c9e6365ba80c5fe85f9761549647037b256c39..9bcf08bcf9fde142dad0c6e3fdde4eeea49c6f81 100644 (file)
--- a/jsc.pro
+++ b/jsc.pro
@@ -5,6 +5,8 @@ SOURCES = jsc.cpp
 QT -= gui
 CONFIG -= app_bundle
 CONFIG += building-libs
 QT -= gui
 CONFIG -= app_bundle
 CONFIG += building-libs
+win32-*: CONFIG += console
+win32-msvc*: CONFIG += exceptions_off stl_off
 
 include($$PWD/../WebKit.pri)
 
 
 include($$PWD/../WebKit.pri)
 
@@ -13,7 +15,6 @@ CONFIG += link_pkgconfig
 QMAKE_RPATHDIR += $$OUTPUT_DIR/lib
 
 isEmpty(OUTPUT_DIR):OUTPUT_DIR=$$PWD/..
 QMAKE_RPATHDIR += $$OUTPUT_DIR/lib
 
 isEmpty(OUTPUT_DIR):OUTPUT_DIR=$$PWD/..
-include($$OUTPUT_DIR/config.pri)
 CONFIG(debug, debug|release) {
     OBJECTS_DIR = obj/debug
 } else { # Release
 CONFIG(debug, debug|release) {
     OBJECTS_DIR = obj/debug
 } else { # Release
@@ -22,9 +23,13 @@ CONFIG(debug, debug|release) {
 OBJECTS_DIR_WTR = $$OBJECTS_DIR$${QMAKE_DIR_SEP}
 include($$PWD/JavaScriptCore.pri)
 
 OBJECTS_DIR_WTR = $$OBJECTS_DIR$${QMAKE_DIR_SEP}
 include($$PWD/JavaScriptCore.pri)
 
-lessThan(QT_MINOR_VERSION, 4) {
-    DEFINES += QT_BEGIN_NAMESPACE="" QT_END_NAMESPACE=""
-}
-
 *-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2
 *-g++*:QMAKE_CXXFLAGS_RELEASE += -O3
 *-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2
 *-g++*:QMAKE_CXXFLAGS_RELEASE += -O3
+
+symbian {
+    TARGET.CAPABILITY = ReadUserData WriteUserData NetworkServices
+}
+
+mac {
+    LIBS_PRIVATE += -framework AppKit
+}
\ No newline at end of file
index 25e17d775e4adf02cf41259cdf05c6285adb3390..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,150 +0,0 @@
-<?xml version="1.0" ?>
-<!-- 
-Copyright (C) 2007 Kevin Ollivier. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1.  Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
-2.  Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution. 
-3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission. 
-
-THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-JavaScriptCore Bakefile project file.
--->
-
-<makefile>
-    <set var="SRCDIR">.</set>
-
-    <include file="../WebKit/wx/wxwk-settings.bkl"/>
-    <include file="JavaScriptCoreSources.bkl"/>
-
-    <template id="jscore_base" template="icu,pthreads,wxwk_build_settings">
-        <sources>
-            $(JSCORE_API_SOURCES)
-            $(JSCORE_BYTECOMPILER_SOURCES)
-            $(JSCORE_DEBUGGER_SOURCES)
-            $(JSCORE_JSC_SOURCES)
-            $(JSCORE_PCRE_SOURCES)
-            $(JSCORE_PARSER_SOURCES)
-            $(JSCORE_PROFILER_SOURCES)
-            $(JSCORE_RUNTIME_SOURCES)
-            $(JSCORE_VM_SOURCES)
-            $(JSCORE_WTF_SOURCES)
-        </sources>
-
-        <set var="ASSEMBLER_SOURCES">
-            <if cond="WX_PORT=='gtk2'">
-                $(JSCORE_VM_SOURCES_POSIX)
-            </if>
-            <if cond="PLATFORM_OS=='mac'">
-                $(JSCORE_VM_SOURCES_POSIX)
-            </if>
-            <if cond="WX_PORT=='msw'">
-                $(JSCORE_VM_SOURCES_WIN)
-            </if>
-        </set>
-
-        <sources>
-            $(ASSEMBLER_SOURCES)
-        </sources>
-        <install-to>$(WKOUTPUTDIR)</install-to>
-        <pic>on</pic>
-        <threading>multi</threading>
-
-        <include>$(SRCDIR)</include>
-        <include>$(SRCDIR)/..</include>
-        <include>$(SRCDIR)/API</include>
-        <include>$(SRCDIR)/assembler</include>
-        <include>$(SRCDIR)/bytecompiler</include>
-        <include>$(SRCDIR)/DerivedSources/JavaScriptCore</include>
-        <include>$(SRCDIR)/ForwardingHeaders</include>
-        <include>$(SRCDIR)/debugger</include>
-        <include>$(SRCDIR)/parser</include>
-        <include>$(SRCDIR)/pcre</include>
-        <include>$(SRCDIR)/profiler</include>
-        <include>$(SRCDIR)/runtime</include>
-        <include>$(SRCDIR)/interpreter</include>
-        <include>$(SRCDIR)/bytecode</include>
-        <include>$(SRCDIR)/wrec</include>
-        <include>$(SRCDIR)/jit</include>
-        <include>$(SRCDIR)/wtf</include>
-        <include>$(SRCDIR)/wtf/unicode</include>
-
-        <define>ENABLE_XSLT=1</define>
-
-        <if cond="FORMAT=='gnu'">
-            <!-- FIXME: we need proper configure checks -->
-            <define>HAVE_FUNC_ISNAN</define>
-            <!-- check for undefined symbols for debugging reasons -->
-            <ldflags>-Wl</ldflags>
-        </if>
-
-        <if cond="PLATFORM_WIN32=='1'">
-            <include>$(SRCDIR)/os-win32</include>
-            <define>HAVE_SYS_TIMEB_H=1</define>
-            <define>HAVE_FLOAT_H=1</define>
-            <define>HAVE_FUNC__FINITE=1</define>
-        </if>
-
-    </template>
-    
-    <exe id="jsc" template="icu,jscore,pthreads,wxwk">
-        <cxx-rtti>off</cxx-rtti>
-        <cxx-exceptions>off</cxx-exceptions>
-        <debug-info>on</debug-info>
-        <depends>jscore</depends>
-        <include>$(SRCDIR)</include>
-        <include>$(WK_ROOT)/JavaScriptCore</include>
-        <include>$(WK_ROOT)/JavaScriptCore/assembler</include>
-        <include>$(WK_ROOT)/JavaScriptCore/bytecompiler</include>
-        <include>$(WK_ROOT)/JavaScriptCore/debugger</include>
-        <include>$(WK_ROOT)/JavaScriptCore/parser</include>
-        <include>$(WK_ROOT)/JavaScriptCore/pcre</include>
-        <include>$(WK_ROOT)/JavaScriptCore/profiler</include>
-        <include>$(WK_ROOT)/JavaScriptCore/runtime</include>
-        <include>$(WK_ROOT)/JavaScriptCore/interpreter</include>
-        <include>$(WK_ROOT)/JavaScriptCore/bytecode</include>
-        <include>$(WK_ROOT)/JavaScriptCore/jit</include>
-        <include>$(WK_ROOT)/JavaScriptCore/wrec</include>
-        <include>$(WK_ROOT)/JavaScriptCore/wtf</include>
-        <dirname>$(WKOUTPUTDIR)</dirname>
-        <sources>$(SRCDIR)/jsc.cpp</sources>
-        <set var="READLINE_LIB">
-            <if cond="WX_PORT=='mac'">edit</if>
-        </set>
-        <sys-lib>$(READLINE_LIB)</sys-lib>
-        <if cond="FORMAT in ['msvc','msvs2005prj']">
-            <include>$(WK_ROOT)/WebKitLibraries/win/include</include>
-            <sys-lib>winmm</sys-lib> <!-- for timeGetTime -->
-            <lib-path>$(WKOUTPUTDIR)</lib-path>
-            <lib-path>$(WK_ROOT)/WebKitLibraries/win/lib</lib-path>
-        </if>
-        
-    </exe>
-
-    <action id="DerivedSources">
-        <is-phony />
-        <command>bash make-generated-sources.sh</command>
-    </action>
-
-    <lib id="jscore" template="jscore_base,wx-lib">
-
-    </lib>
-</makefile>
diff --git a/os-win32/WinMain.cpp b/os-win32/WinMain.cpp
new file mode 100644 (file)
index 0000000..17800d0
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  Copyright (C) 2009 Patrick Gansterer (paroga@paroga.com)
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Vector.h"
+#include <winbase.h>
+#include <winnls.h>
+#include <wtf/UnusedParam.h>
+
+int main(int argc, char** argv);
+
+static inline char* convertToUtf8(LPCWSTR widecharString, int length)
+{
+    int requiredSize = WideCharToMultiByte(CP_UTF8, 0, widecharString, length, 0, 0, 0, 0);
+    char* multibyteString = new char[requiredSize + 1];
+
+    WideCharToMultiByte(CP_UTF8, 0, widecharString, length, multibyteString, requiredSize, 0, 0);
+    multibyteString[requiredSize] = '\0';
+
+    return multibyteString;
+}
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
+{
+    UNUSED_PARAM(hInstance);
+    UNUSED_PARAM(hPrevInstance);
+    UNUSED_PARAM(nCmdShow);
+
+    Vector<char*> arguments;
+    TCHAR buffer[MAX_PATH];
+
+    int length = GetModuleFileNameW(0, buffer, MAX_PATH);
+    arguments.append(convertToUtf8(buffer, length));
+
+    WCHAR* commandLine = lpCmdLine;
+    while (commandLine[0] != '\0') {
+        int commandLineLength = 1;
+        WCHAR endChar = ' ';
+
+        while (commandLine[0] == ' ')
+            ++commandLine;
+
+        if (commandLine[0] == '\"') {
+            ++commandLine;
+            endChar = '\"';
+        }
+
+        while (commandLine[commandLineLength] != endChar && commandLine[commandLineLength] != '\0')
+            ++commandLineLength;
+
+        arguments.append(convertToUtf8(commandLine, commandLineLength));
+
+        commandLine += commandLineLength;
+        if (endChar != ' ' && commandLine[0] != '\0')
+            ++commandLine;
+    }
+
+    int res = main(arguments.size(), arguments.data());
+
+    for (size_t i = 0; i < arguments.size(); i++)
+        delete arguments[i];
+
+    return res;
+}
index 8e7baceac1a1591877c5745d1e7527c75d8ed20f..fc8ee28f400a115b2d5bf167805cdd53b8eaf66b 100644 (file)
@@ -21,8 +21,8 @@
 #ifndef STDBOOL_WIN32_H
 #define STDBOOL_WIN32_H
 
 #ifndef STDBOOL_WIN32_H
 #define STDBOOL_WIN32_H
 
-#if !PLATFORM(WIN_OS)
-#error "This stdbool.h file should only be compiled under Windows"
+#if !COMPILER(MSVC)
+#error "This stdbool.h file should only be compiled with MSVC"
 #endif
 
 #ifndef __cplusplus
 #endif
 
 #ifndef __cplusplus
index efab2ae5474de0989ee13735677ee3be496d6a03..1d8787e051343b1c63f9c417923c9a64e3c7cec5 100644 (file)
 
 #include <wtf/Platform.h>
 
 
 #include <wtf/Platform.h>
 
-/* This file emulates enough of stdint.h on Windows to make JavaScriptCore and WebCore compile. */
+/* This file emulates enough of stdint.h on Windows to make JavaScriptCore and WebCore
+   compile using MSVC which does not ship with the stdint.h header. */
 
 
-#if !PLATFORM(WIN_OS)
-#error "This stdint.h file should only be compiled under Windows"
+#if !COMPILER(MSVC)
+#error "This stdint.h file should only be compiled with MSVC"
 #endif
 
 #include <limits.h>
 #endif
 
 #include <limits.h>
index c5ca4250a4522d61df40b3ad658e4cc330cbb211..717a266819397a96ff7a84e45f7570e4834cbd9d 100644 (file)
 
 #include "config.h"
 
 
 #include "config.h"
 
-#include <string.h>
-#include <stdlib.h>
-#include "JSValue.h"
 #include "JSObject.h"
 #include "JSObject.h"
-#include "NodeConstructors.h"
-#include "Lexer.h"
 #include "JSString.h"
 #include "JSString.h"
-#include "JSGlobalData.h"
-#include "CommonIdentifiers.h"
+#include "Lexer.h"
+#include "NodeConstructors.h"
 #include "NodeInfo.h"
 #include "NodeInfo.h"
-#include "Parser.h"
+#include <stdlib.h>
+#include <string.h>
 #include <wtf/MathExtras.h>
 
 #include <wtf/MathExtras.h>
 
+#define YYMALLOC fastMalloc
+#define YYFREE fastFree
+
 #define YYMAXDEPTH 10000
 #define YYENABLE_NLS 0
 
 #define YYMAXDEPTH 10000
 #define YYENABLE_NLS 0
 
-/* default values for bison */
+// Default values for bison.
 #define YYDEBUG 0 // Set to 1 to debug a parse error.
 #define jscyydebug 0 // Set to 1 to debug a parse error.
 #define YYDEBUG 0 // Set to 1 to debug a parse error.
 #define jscyydebug 0 // Set to 1 to debug a parse error.
-#if !PLATFORM(DARWIN)
-    // avoid triggering warnings in older bison
+#if !OS(DARWIN)
+// Avoid triggering warnings in older bison by not setting this on the Darwin platform.
+// FIXME: Is this still needed?
 #define YYERROR_VERBOSE
 #endif
 
 #define YYERROR_VERBOSE
 #endif
 
-int jscyylex(void* lvalp, void* llocp, void* globalPtr);
 int jscyyerror(const char*);
 int jscyyerror(const char*);
+
 static inline bool allowAutomaticSemicolon(JSC::Lexer&, int);
 
 #define GLOBAL_DATA static_cast<JSGlobalData*>(globalPtr)
 static inline bool allowAutomaticSemicolon(JSC::Lexer&, int);
 
 #define GLOBAL_DATA static_cast<JSGlobalData*>(globalPtr)
-#define LEXER (GLOBAL_DATA->lexer)
-
-#define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*LEXER, yychar)) YYABORT; } while (0)
-#define SET_EXCEPTION_LOCATION(node, start, divot, end) node->setExceptionSourceCode((divot), (divot) - (start), (end) - (divot))
-#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line)
+#define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*GLOBAL_DATA->lexer, yychar)) YYABORT; } while (0)
 
 using namespace JSC;
 using namespace std;
 
 
 using namespace JSC;
 using namespace std;
 
-static ExpressionNode* makeAssignNode(void*, ExpressionNode* loc, Operator, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end);
-static ExpressionNode* makePrefixNode(void*, ExpressionNode* expr, Operator, int start, int divot, int end);
-static ExpressionNode* makePostfixNode(void*, ExpressionNode* expr, Operator, int start, int divot, int end);
-static PropertyNode* makeGetterOrSetterPropertyNode(void*, const Identifier &getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*, const SourceCode&);
-static ExpressionNodeInfo makeFunctionCallNode(void*, ExpressionNodeInfo func, ArgumentsNodeInfo, int start, int divot, int end);
-static ExpressionNode* makeTypeOfNode(void*, ExpressionNode*);
-static ExpressionNode* makeDeleteNode(void*, ExpressionNode*, int start, int divot, int end);
-static ExpressionNode* makeNegateNode(void*, ExpressionNode*);
-static NumberNode* makeNumberNode(void*, double);
-static ExpressionNode* makeBitwiseNotNode(void*, ExpressionNode*);
-static ExpressionNode* makeMultNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static ExpressionNode* makeDivNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static ExpressionNode* makeAddNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static ExpressionNode* makeSubNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static ExpressionNode* makeLeftShiftNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static ExpressionNode* makeRightShiftNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
-static StatementNode* makeVarStatementNode(void*, ExpressionNode*);
-static ExpressionNode* combineCommaNodes(void*, ExpressionNode* list, ExpressionNode* init);
+static ExpressionNode* makeAssignNode(JSGlobalData*, ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, int start, int divot, int end);
+static ExpressionNode* makePrefixNode(JSGlobalData*, ExpressionNode*, Operator, int start, int divot, int end);
+static ExpressionNode* makePostfixNode(JSGlobalData*, ExpressionNode*, Operator, int start, int divot, int end);
+static PropertyNode* makeGetterOrSetterPropertyNode(JSGlobalData*, const Identifier& getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*, const SourceCode&);
+static ExpressionNodeInfo makeFunctionCallNode(JSGlobalData*, ExpressionNodeInfo function, ArgumentsNodeInfo, int start, int divot, int end);
+static ExpressionNode* makeTypeOfNode(JSGlobalData*, ExpressionNode*);
+static ExpressionNode* makeDeleteNode(JSGlobalData*, ExpressionNode*, int start, int divot, int end);
+static ExpressionNode* makeNegateNode(JSGlobalData*, ExpressionNode*);
+static NumberNode* makeNumberNode(JSGlobalData*, double);
+static ExpressionNode* makeBitwiseNotNode(JSGlobalData*, ExpressionNode*);
+static ExpressionNode* makeMultNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+static ExpressionNode* makeDivNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+static ExpressionNode* makeAddNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+static ExpressionNode* makeSubNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+static ExpressionNode* makeLeftShiftNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+static ExpressionNode* makeRightShiftNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+static StatementNode* makeVarStatementNode(JSGlobalData*, ExpressionNode*);
+static ExpressionNode* combineCommaNodes(JSGlobalData*, ExpressionNode* list, ExpressionNode* init);
 
 #if COMPILER(MSVC)
 
 
 #if COMPILER(MSVC)
 
@@ -88,28 +84,22 @@ static ExpressionNode* combineCommaNodes(void*, ExpressionNode* list, Expression
 #pragma warning(disable: 4244)
 #pragma warning(disable: 4702)
 
 #pragma warning(disable: 4244)
 #pragma warning(disable: 4702)
 
-// At least some of the time, the declarations of malloc and free that bison
-// generates are causing warnings. A way to avoid this is to explicitly define
-// the macros so that bison doesn't try to declare malloc and free.
-#define YYMALLOC malloc
-#define YYFREE free
-
 #endif
 
 #define YYPARSE_PARAM globalPtr
 #define YYLEX_PARAM globalPtr
 
 #endif
 
 #define YYPARSE_PARAM globalPtr
 #define YYLEX_PARAM globalPtr
 
-template <typename T> NodeDeclarationInfo<T> createNodeDeclarationInfo(T node, ParserArenaData<DeclarationStacks::VarStack>* varDecls, 
-                                                                       ParserArenaData<DeclarationStacks::FunctionStack>* funcDecls,
-                                                                       CodeFeatures info,
-                                                                       int numConstants) 
+template <typename T> inline NodeDeclarationInfo<T> createNodeDeclarationInfo(T node,
+    ParserArenaData<DeclarationStacks::VarStack>* varDecls,
+    ParserArenaData<DeclarationStacks::FunctionStack>* funcDecls,
+    CodeFeatures info, int numConstants) 
 {
     ASSERT((info & ~AllFeatures) == 0);
     NodeDeclarationInfo<T> result = { node, varDecls, funcDecls, info, numConstants };
     return result;
 }
 
 {
     ASSERT((info & ~AllFeatures) == 0);
     NodeDeclarationInfo<T> result = { node, varDecls, funcDecls, info, numConstants };
     return result;
 }
 
-template <typename T> NodeInfo<T> createNodeInfo(T node, CodeFeatures info, int numConstants)
+template <typename T> inline NodeInfo<T> createNodeInfo(T node, CodeFeatures info, int numConstants)
 {
     ASSERT((info & ~AllFeatures) == 0);
     NodeInfo<T> result = { node, info, numConstants };
 {
     ASSERT((info & ~AllFeatures) == 0);
     NodeInfo<T> result = { node, info, numConstants };
@@ -135,21 +125,20 @@ template <typename T> inline T mergeDeclarationLists(T decls1, T decls2)
     return decls1;
 }
 
     return decls1;
 }
 
-static void appendToVarDeclarationList(void* globalPtr, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
+static inline void appendToVarDeclarationList(JSGlobalData* globalData, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
 {
     if (!varDecls)
 {
     if (!varDecls)
-        varDecls = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
-
-    varDecls->data.append(make_pair(ident, attrs));
+        varDecls = new (globalData) ParserArenaData<DeclarationStacks::VarStack>;
 
 
+    varDecls->data.append(make_pair(&ident, attrs));
 }
 
 }
 
-static inline void appendToVarDeclarationList(void* globalPtr, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl)
+static inline void appendToVarDeclarationList(JSGlobalData* globalData, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl)
 {
     unsigned attrs = DeclarationStacks::IsConstant;
     if (decl->hasInitializer())
         attrs |= DeclarationStacks::HasInitializer;        
 {
     unsigned attrs = DeclarationStacks::IsConstant;
     if (decl->hasInitializer())
         attrs |= DeclarationStacks::HasInitializer;        
-    appendToVarDeclarationList(globalPtr, varDecls, decl->ident(), attrs);
+    appendToVarDeclarationList(globalData, varDecls, decl->ident(), attrs);
 }
 
 %}
 }
 
 %}
@@ -157,7 +146,7 @@ static inline void appendToVarDeclarationList(void* globalPtr, ParserArenaData<D
 %union {
     int                 intValue;
     double              doubleValue;
 %union {
     int                 intValue;
     double              doubleValue;
-    Identifier*         ident;
+    const Identifier*   ident;
 
     // expression subtrees
     ExpressionNodeInfo  expressionNode;
 
     // expression subtrees
     ExpressionNodeInfo  expressionNode;
@@ -186,6 +175,20 @@ static inline void appendToVarDeclarationList(void* globalPtr, ParserArenaData<D
     Operator            op;
 }
 
     Operator            op;
 }
 
+%{
+
+template <typename T> inline void setStatementLocation(StatementNode* statement, const T& start, const T& end)
+{
+    statement->setLoc(start.first_line, end.last_line);
+}
+
+static inline void setExceptionLocation(ThrowableExpressionData* node, unsigned start, unsigned divot, unsigned end)
+{
+    node->setExceptionSourceCode(divot, divot - start, end - divot);
+}
+
+%}
+
 %start Program
 
 /* literals */
 %start Program
 
 /* literals */
@@ -293,21 +296,25 @@ Literal:
   | NUMBER                              { $$ = createNodeInfo<ExpressionNode*>(makeNumberNode(GLOBAL_DATA, $1), 0, 1); }
   | STRING                              { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StringNode(GLOBAL_DATA, *$1), 0, 1); }
   | '/' /* regexp */                    {
   | NUMBER                              { $$ = createNodeInfo<ExpressionNode*>(makeNumberNode(GLOBAL_DATA, $1), 0, 1); }
   | STRING                              { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StringNode(GLOBAL_DATA, *$1), 0, 1); }
   | '/' /* regexp */                    {
-                                            Lexer& l = *LEXER;
-                                            if (!l.scanRegExp())
+                                            Lexer& l = *GLOBAL_DATA->lexer;
+                                            const Identifier* pattern;
+                                            const Identifier* flags;
+                                            if (!l.scanRegExp(pattern, flags))
                                                 YYABORT;
                                                 YYABORT;
-                                            RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, l.pattern(), l.flags());
-                                            int size = l.pattern().size() + 2; // + 2 for the two /'s
-                                            SET_EXCEPTION_LOCATION(node, @1.first_column, @1.first_column + size, @1.first_column + size);
+                                            RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, *pattern, *flags);
+                                            int size = pattern->size() + 2; // + 2 for the two /'s
+                                            setExceptionLocation(node, @1.first_column, @1.first_column + size, @1.first_column + size);
                                             $$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
                                         }
   | DIVEQUAL /* regexp with /= */       {
                                             $$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
                                         }
   | DIVEQUAL /* regexp with /= */       {
-                                            Lexer& l = *LEXER;
-                                            if (!l.scanRegExp())
+                                            Lexer& l = *GLOBAL_DATA->lexer;
+                                            const Identifier* pattern;
+                                            const Identifier* flags;
+                                            if (!l.scanRegExp(pattern, flags, '='))
                                                 YYABORT;
                                                 YYABORT;
-                                            RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, "=" + l.pattern(), l.flags());
-                                            int size = l.pattern().size() + 2; // + 2 for the two /'s
-                                            SET_EXCEPTION_LOCATION(node, @1.first_column, @1.first_column + size, @1.first_column + size);
+                                            RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, *pattern, *flags);
+                                            int size = pattern->size() + 2; // + 2 for the two /'s
+                                            setExceptionLocation(node, @1.first_column, @1.first_column + size, @1.first_column + size);
                                             $$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
                                         }
 ;
                                             $$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
                                         }
 ;
@@ -315,14 +322,14 @@ Literal:
 Property:
     IDENT ':' AssignmentExpr            { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
   | STRING ':' AssignmentExpr           { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
 Property:
     IDENT ':' AssignmentExpr            { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
   | STRING ':' AssignmentExpr           { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
-  | NUMBER ':' AssignmentExpr           { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, Identifier(GLOBAL_DATA, UString::from($1)), $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
-  | IDENT IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE    { $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(globalPtr, *$1, *$2, 0, $6, LEXER->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); DBG($6, @5, @7); if (!$$.m_node) YYABORT; }
+  | NUMBER ':' AssignmentExpr           { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, $1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
+  | IDENT IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE    { $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(GLOBAL_DATA, *$1, *$2, 0, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); setStatementLocation($6, @5, @7); if (!$$.m_node) YYABORT; }
   | IDENT IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
                                                              {
   | IDENT IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
                                                              {
-                                                                 $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(globalPtr, *$1, *$2, $4.m_node.head, $7, LEXER->sourceCode($6, $8, @6.first_line)), $4.m_features | ClosureFeature, 0); 
+                                                                 $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(GLOBAL_DATA, *$1, *$2, $4.m_node.head, $7, GLOBAL_DATA->lexer->sourceCode($6, $8, @6.first_line)), $4.m_features | ClosureFeature, 0); 
                                                                  if ($4.m_features & ArgumentsFeature)
                                                                      $7->setUsesArguments(); 
                                                                  if ($4.m_features & ArgumentsFeature)
                                                                      $7->setUsesArguments(); 
-                                                                 DBG($7, @6, @8); 
+                                                                 setStatementLocation($7, @6, @8); 
                                                                  if (!$$.m_node) 
                                                                      YYABORT; 
                                                              }
                                                                  if (!$$.m_node) 
                                                                      YYABORT; 
                                                              }
@@ -387,15 +394,15 @@ MemberExpr:
     PrimaryExpr
   | FunctionExpr                        { $$ = createNodeInfo<ExpressionNode*>($1.m_node, $1.m_features, $1.m_numConstants); }
   | MemberExpr '[' Expr ']'             { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
     PrimaryExpr
   | FunctionExpr                        { $$ = createNodeInfo<ExpressionNode*>($1.m_node, $1.m_features, $1.m_numConstants); }
   | MemberExpr '[' Expr ']'             { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @4.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
                                         }
   | MemberExpr '.' IDENT                { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
                                         }
   | MemberExpr '.' IDENT                { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @3.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
                                         }
   | NEW MemberExpr Arguments            { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
                                         }
   | NEW MemberExpr Arguments            { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @3.last_column);
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @3.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
                                         }
 ;
                                           $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
                                         }
 ;
@@ -403,15 +410,15 @@ MemberExpr:
 MemberExprNoBF:
     PrimaryExprNoBrace
   | MemberExprNoBF '[' Expr ']'         { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
 MemberExprNoBF:
     PrimaryExprNoBrace
   | MemberExprNoBF '[' Expr ']'         { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @4.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
                                         }
   | MemberExprNoBF '.' IDENT            { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
                                         }
   | MemberExprNoBF '.' IDENT            { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @3.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
                                         }
   | NEW MemberExpr Arguments            { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
                                         }
   | NEW MemberExpr Arguments            { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @3.last_column);
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @3.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
                                         }
 ;
                                           $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
                                         }
 ;
@@ -419,7 +426,7 @@ MemberExprNoBF:
 NewExpr:
     MemberExpr
   | NEW NewExpr                         { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node);
 NewExpr:
     MemberExpr
   | NEW NewExpr                         { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants); 
                                         }
 ;
                                           $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants); 
                                         }
 ;
@@ -427,32 +434,32 @@ NewExpr:
 NewExprNoBF:
     MemberExprNoBF
   | NEW NewExpr                         { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node);
 NewExprNoBF:
     MemberExprNoBF
   | NEW NewExpr                         { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants);
                                         }
 ;
 
 CallExpr:
                                           $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants);
                                         }
 ;
 
 CallExpr:
-    MemberExpr Arguments                { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
-  | CallExpr Arguments                  { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+    MemberExpr Arguments                { $$ = makeFunctionCallNode(GLOBAL_DATA, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+  | CallExpr Arguments                  { $$ = makeFunctionCallNode(GLOBAL_DATA, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
   | CallExpr '[' Expr ']'               { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
   | CallExpr '[' Expr ']'               { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @4.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
                                         }
   | CallExpr '.' IDENT                  { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
                                         }
   | CallExpr '.' IDENT                  { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @3.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); }
 ;
 
 CallExprNoBF:
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); }
 ;
 
 CallExprNoBF:
-    MemberExprNoBF Arguments            { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
-  | CallExprNoBF Arguments              { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+    MemberExprNoBF Arguments            { $$ = makeFunctionCallNode(GLOBAL_DATA, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+  | CallExprNoBF Arguments              { $$ = makeFunctionCallNode(GLOBAL_DATA, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
   | CallExprNoBF '[' Expr ']'           { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
   | CallExprNoBF '[' Expr ']'           { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @4.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
                                         }
   | CallExprNoBF '.' IDENT              { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
                                         }
   | CallExprNoBF '.' IDENT              { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @3.last_column);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); 
                                         }
 ;
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); 
                                         }
 ;
@@ -570,10 +577,10 @@ RelationalExpr:
   | RelationalExpr LE ShiftExpr         { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExpr GE ShiftExpr         { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExpr INSTANCEOF ShiftExpr { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
   | RelationalExpr LE ShiftExpr         { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExpr GE ShiftExpr         { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExpr INSTANCEOF ShiftExpr { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);  
+                                          setExceptionLocation(node, @1.first_column, @3.first_column, @3.last_column);  
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExpr INTOKEN ShiftExpr    { InNode* node = new (GLOBAL_DATA) InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExpr INTOKEN ShiftExpr    { InNode* node = new (GLOBAL_DATA) InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);  
+                                          setExceptionLocation(node, @1.first_column, @3.first_column, @3.last_column);  
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
 ;
 
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
 ;
 
@@ -585,7 +592,7 @@ RelationalExprNoIn:
   | RelationalExprNoIn GE ShiftExpr     { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExprNoIn INSTANCEOF ShiftExpr
                                         { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
   | RelationalExprNoIn GE ShiftExpr     { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExprNoIn INSTANCEOF ShiftExpr
                                         { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);  
+                                          setExceptionLocation(node, @1.first_column, @3.first_column, @3.last_column);  
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
 ;
 
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
 ;
 
@@ -597,11 +604,11 @@ RelationalExprNoBF:
   | RelationalExprNoBF GE ShiftExpr     { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExprNoBF INSTANCEOF ShiftExpr
                                         { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
   | RelationalExprNoBF GE ShiftExpr     { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExprNoBF INSTANCEOF ShiftExpr
                                         { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);  
+                                          setExceptionLocation(node, @1.first_column, @3.first_column, @3.last_column);  
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExprNoBF INTOKEN ShiftExpr 
                                         { InNode* node = new (GLOBAL_DATA) InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
   | RelationalExprNoBF INTOKEN ShiftExpr 
                                         { InNode* node = new (GLOBAL_DATA) InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);  
+                                          setExceptionLocation(node, @1.first_column, @3.first_column, @3.last_column);  
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
 ;
 
                                           $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
 ;
 
@@ -812,17 +819,17 @@ Statement:
 ;
 
 Block:
 ;
 
 Block:
-    OPENBRACE CLOSEBRACE                             { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, 0), 0, 0, 0, 0);
-                                          DBG($$.m_node, @1, @2); }
-  | OPENBRACE SourceElements CLOSEBRACE              { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
-                                          DBG($$.m_node, @1, @3); }
+    OPENBRACE CLOSEBRACE                { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, 0), 0, 0, 0, 0);
+                                          setStatementLocation($$.m_node, @1, @2); }
+  | OPENBRACE SourceElements CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+                                          setStatementLocation($$.m_node, @1, @3); }
 ;
 
 VariableStatement:
     VAR VariableDeclarationList ';'     { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
 ;
 
 VariableStatement:
     VAR VariableDeclarationList ';'     { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
-                                          DBG($$.m_node, @1, @3); }
+                                          setStatementLocation($$.m_node, @1, @3); }
   | VAR VariableDeclarationList error   { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
   | VAR VariableDeclarationList error   { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
-                                          DBG($$.m_node, @1, @2);
+                                          setStatementLocation($$.m_node, @1, @2);
                                           AUTO_SEMICOLON; }
 ;
 
                                           AUTO_SEMICOLON; }
 ;
 
@@ -835,7 +842,7 @@ VariableDeclarationList:
                                           $$.m_numConstants = 0;
                                         }
   | IDENT Initializer                   { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
                                           $$.m_numConstants = 0;
                                         }
   | IDENT Initializer                   { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.first_column + 1, @2.last_column);
+                                          setExceptionLocation(node, @1.first_column, @2.first_column + 1, @2.last_column);
                                           $$.m_node = node;
                                           $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
                                           appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
                                           $$.m_node = node;
                                           $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
                                           appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
@@ -853,7 +860,7 @@ VariableDeclarationList:
                                         }
   | VariableDeclarationList ',' IDENT Initializer
                                         { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
                                         }
   | VariableDeclarationList ',' IDENT Initializer
                                         { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @3.first_column, @4.first_column + 1, @4.last_column);
+                                          setExceptionLocation(node, @3.first_column, @4.first_column + 1, @4.last_column);
                                           $$.m_node = combineCommaNodes(GLOBAL_DATA, $1.m_node, node);
                                           $$.m_varDeclarations = $1.m_varDeclarations;
                                           appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
                                           $$.m_node = combineCommaNodes(GLOBAL_DATA, $1.m_node, node);
                                           $$.m_varDeclarations = $1.m_varDeclarations;
                                           appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
@@ -872,7 +879,7 @@ VariableDeclarationListNoIn:
                                           $$.m_numConstants = 0;
                                         }
   | IDENT InitializerNoIn               { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
                                           $$.m_numConstants = 0;
                                         }
   | IDENT InitializerNoIn               { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.first_column + 1, @2.last_column);
+                                          setExceptionLocation(node, @1.first_column, @2.first_column + 1, @2.last_column);
                                           $$.m_node = node;
                                           $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
                                           appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
                                           $$.m_node = node;
                                           $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
                                           appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
@@ -890,7 +897,7 @@ VariableDeclarationListNoIn:
                                         }
   | VariableDeclarationListNoIn ',' IDENT InitializerNoIn
                                         { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
                                         }
   | VariableDeclarationListNoIn ',' IDENT InitializerNoIn
                                         { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
-                                          SET_EXCEPTION_LOCATION(node, @3.first_column, @4.first_column + 1, @4.last_column);
+                                          setExceptionLocation(node, @3.first_column, @4.first_column + 1, @4.last_column);
                                           $$.m_node = combineCommaNodes(GLOBAL_DATA, $1.m_node, node);
                                           $$.m_varDeclarations = $1.m_varDeclarations;
                                           appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
                                           $$.m_node = combineCommaNodes(GLOBAL_DATA, $1.m_node, node);
                                           $$.m_varDeclarations = $1.m_varDeclarations;
                                           appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
@@ -902,10 +909,10 @@ VariableDeclarationListNoIn:
 
 ConstStatement:
     CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
 
 ConstStatement:
     CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
-                                          DBG($$.m_node, @1, @3); }
+                                          setStatementLocation($$.m_node, @1, @3); }
   | CONSTTOKEN ConstDeclarationList error
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
   | CONSTTOKEN ConstDeclarationList error
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
-                                          DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+                                          setStatementLocation($$.m_node, @1, @2); AUTO_SEMICOLON; }
 ;
 
 ConstDeclarationList:
 ;
 
 ConstDeclarationList:
@@ -947,36 +954,36 @@ EmptyStatement:
 
 ExprStatement:
     ExprNoBF ';'                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
 
 ExprStatement:
     ExprNoBF ';'                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
-                                          DBG($$.m_node, @1, @2); }
+                                          setStatementLocation($$.m_node, @1, @2); }
   | ExprNoBF error                      { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
   | ExprNoBF error                      { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
-                                          DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+                                          setStatementLocation($$.m_node, @1, @1); AUTO_SEMICOLON; }
 ;
 
 IfStatement:
     IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) IfNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
 ;
 
 IfStatement:
     IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) IfNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
-                                          DBG($$.m_node, @1, @4); }
+                                          setStatementLocation($$.m_node, @1, @4); }
   | IF '(' Expr ')' Statement ELSE Statement
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) IfElseNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node), 
                                                                                          mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations),
                                                                                          mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations),
                                                                                          $3.m_features | $5.m_features | $7.m_features,
                                                                                          $3.m_numConstants + $5.m_numConstants + $7.m_numConstants); 
   | IF '(' Expr ')' Statement ELSE Statement
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) IfElseNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node), 
                                                                                          mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations),
                                                                                          mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations),
                                                                                          $3.m_features | $5.m_features | $7.m_features,
                                                                                          $3.m_numConstants + $5.m_numConstants + $7.m_numConstants); 
-                                          DBG($$.m_node, @1, @4); }
+                                          setStatementLocation($$.m_node, @1, @4); }
 ;
 
 IterationStatement:
     DO Statement WHILE '(' Expr ')' ';'    { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
 ;
 
 IterationStatement:
     DO Statement WHILE '(' Expr ')' ';'    { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
-                                             DBG($$.m_node, @1, @3); }
+                                             setStatementLocation($$.m_node, @1, @3); }
   | DO Statement WHILE '(' Expr ')' error  { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
   | DO Statement WHILE '(' Expr ')' error  { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
-                                             DBG($$.m_node, @1, @3); } // Always performs automatic semicolon insertion.
+                                             setStatementLocation($$.m_node, @1, @3); } // Always performs automatic semicolon insertion.
   | WHILE '(' Expr ')' Statement        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) WhileNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
   | WHILE '(' Expr ')' Statement        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) WhileNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
-                                          DBG($$.m_node, @1, @4); }
+                                          setStatementLocation($$.m_node, @1, @4); }
   | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ForNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations, 
                                                                                          $3.m_features | $5.m_features | $7.m_features | $9.m_features,
                                                                                          $3.m_numConstants + $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
   | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ForNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations, 
                                                                                          $3.m_features | $5.m_features | $7.m_features | $9.m_features,
                                                                                          $3.m_numConstants + $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
-                                          DBG($$.m_node, @1, @8); 
+                                          setStatementLocation($$.m_node, @1, @8); 
                                         }
   | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ForNode(GLOBAL_DATA, $4.m_node, $6.m_node, $8.m_node, $10.m_node, true),
                                         }
   | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ForNode(GLOBAL_DATA, $4.m_node, $6.m_node, $8.m_node, $10.m_node, true),
@@ -984,30 +991,30 @@ IterationStatement:
                                                                                          mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations),
                                                                                          $4.m_features | $6.m_features | $8.m_features | $10.m_features,
                                                                                          $4.m_numConstants + $6.m_numConstants + $8.m_numConstants + $10.m_numConstants);
                                                                                          mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations),
                                                                                          $4.m_features | $6.m_features | $8.m_features | $10.m_features,
                                                                                          $4.m_numConstants + $6.m_numConstants + $8.m_numConstants + $10.m_numConstants);
-                                          DBG($$.m_node, @1, @9); }
+                                          setStatementLocation($$.m_node, @1, @9); }
   | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement
                                         {
                                             ForInNode* node = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node);
   | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement
                                         {
                                             ForInNode* node = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node);
-                                            SET_EXCEPTION_LOCATION(node, @3.first_column, @3.last_column, @5.last_column);
+                                            setExceptionLocation(node, @3.first_column, @3.last_column, @5.last_column);
                                             $$ = createNodeDeclarationInfo<StatementNode*>(node, $7.m_varDeclarations, $7.m_funcDeclarations,
                                                                                            $3.m_features | $5.m_features | $7.m_features,
                                                                                            $3.m_numConstants + $5.m_numConstants + $7.m_numConstants);
                                             $$ = createNodeDeclarationInfo<StatementNode*>(node, $7.m_varDeclarations, $7.m_funcDeclarations,
                                                                                            $3.m_features | $5.m_features | $7.m_features,
                                                                                            $3.m_numConstants + $5.m_numConstants + $7.m_numConstants);
-                                            DBG($$.m_node, @1, @6);
+                                            setStatementLocation($$.m_node, @1, @6);
                                         }
   | FOR '(' VAR IDENT INTOKEN Expr ')' Statement
                                         { ForInNode *forIn = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, *$4, 0, $6.m_node, $8.m_node, @5.first_column, @5.first_column - @4.first_column, @6.last_column - @5.first_column);
                                         }
   | FOR '(' VAR IDENT INTOKEN Expr ')' Statement
                                         { ForInNode *forIn = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, *$4, 0, $6.m_node, $8.m_node, @5.first_column, @5.first_column - @4.first_column, @6.last_column - @5.first_column);
-                                          SET_EXCEPTION_LOCATION(forIn, @4.first_column, @5.first_column + 1, @6.last_column);
+                                          setExceptionLocation(forIn, @4.first_column, @5.first_column + 1, @6.last_column);
                                           appendToVarDeclarationList(GLOBAL_DATA, $8.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
                                           $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $8.m_varDeclarations, $8.m_funcDeclarations, ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $6.m_features | $8.m_features, $6.m_numConstants + $8.m_numConstants);
                                           appendToVarDeclarationList(GLOBAL_DATA, $8.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
                                           $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $8.m_varDeclarations, $8.m_funcDeclarations, ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $6.m_features | $8.m_features, $6.m_numConstants + $8.m_numConstants);
-                                          DBG($$.m_node, @1, @7); }
+                                          setStatementLocation($$.m_node, @1, @7); }
   | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement
                                         { ForInNode *forIn = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, *$4, $5.m_node, $7.m_node, $9.m_node, @5.first_column, @5.first_column - @4.first_column, @5.last_column - @5.first_column);
   | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement
                                         { ForInNode *forIn = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, *$4, $5.m_node, $7.m_node, $9.m_node, @5.first_column, @5.first_column - @4.first_column, @5.last_column - @5.first_column);
-                                          SET_EXCEPTION_LOCATION(forIn, @4.first_column, @6.first_column + 1, @7.last_column);
+                                          setExceptionLocation(forIn, @4.first_column, @6.first_column + 1, @7.last_column);
                                           appendToVarDeclarationList(GLOBAL_DATA, $9.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
                                           $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $9.m_varDeclarations, $9.m_funcDeclarations,
                                                                                          ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $5.m_features | $7.m_features | $9.m_features,
                                                                                          $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
                                           appendToVarDeclarationList(GLOBAL_DATA, $9.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
                                           $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $9.m_varDeclarations, $9.m_funcDeclarations,
                                                                                          ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $5.m_features | $7.m_features | $9.m_features,
                                                                                          $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
-                                          DBG($$.m_node, @1, @8); }
+                                          setStatementLocation($$.m_node, @1, @8); }
 ;
 
 ExprOpt:
 ;
 
 ExprOpt:
@@ -1022,63 +1029,63 @@ ExprNoInOpt:
 
 ContinueStatement:
     CONTINUE ';'                        { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA);
 
 ContinueStatement:
     CONTINUE ';'                        { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column); 
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column); 
                                           $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
                                           $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
-                                          DBG($$.m_node, @1, @2); }
+                                          setStatementLocation($$.m_node, @1, @2); }
   | CONTINUE error                      { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA);
   | CONTINUE error                      { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column); 
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column); 
                                           $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
                                           $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
-                                          DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+                                          setStatementLocation($$.m_node, @1, @1); AUTO_SEMICOLON; }
   | CONTINUE IDENT ';'                  { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA, *$2);
   | CONTINUE IDENT ';'                  { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA, *$2);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); 
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column); 
                                           $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
                                           $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
-                                          DBG($$.m_node, @1, @3); }
+                                          setStatementLocation($$.m_node, @1, @3); }
   | CONTINUE IDENT error                { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA, *$2);
   | CONTINUE IDENT error                { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA, *$2);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); 
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column); 
                                           $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
                                           $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
-                                          DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+                                          setStatementLocation($$.m_node, @1, @2); AUTO_SEMICOLON; }
 ;
 
 BreakStatement:
     BREAK ';'                           { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA);
 ;
 
 BreakStatement:
     BREAK ';'                           { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); }
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column);
+                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @2); }
   | BREAK error                         { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA);
   | BREAK error                         { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA), 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column);
+                                          $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA), 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @1); AUTO_SEMICOLON; }
   | BREAK IDENT ';'                     { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2);
   | BREAK IDENT ';'                     { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @3); }
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
+                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @3); }
   | BREAK IDENT error                   { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2);
   | BREAK IDENT error                   { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2), 0, 0, 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
+                                          $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2), 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @2); AUTO_SEMICOLON; }
 ;
 
 ReturnStatement:
     RETURN ';'                          { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, 0); 
 ;
 
 ReturnStatement:
     RETURN ';'                          { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, 0); 
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column); 
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); }
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column); 
+                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @2); }
   | RETURN error                        { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, 0); 
   | RETURN error                        { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, 0); 
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column); 
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column); 
+                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @1); AUTO_SEMICOLON; }
   | RETURN Expr ';'                     { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, $2.m_node); 
   | RETURN Expr ';'                     { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, $2.m_node); 
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @3); }
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
+                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); setStatementLocation($$.m_node, @1, @3); }
   | RETURN Expr error                   { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, $2.m_node); 
   | RETURN Expr error                   { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, $2.m_node); 
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); 
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column); 
+                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); setStatementLocation($$.m_node, @1, @2); AUTO_SEMICOLON; }
 ;
 
 WithStatement:
     WITH '(' Expr ')' Statement         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) WithNode(GLOBAL_DATA, $3.m_node, $5.m_node, @3.last_column, @3.last_column - @3.first_column),
                                                                                          $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features | WithFeature, $3.m_numConstants + $5.m_numConstants);
 ;
 
 WithStatement:
     WITH '(' Expr ')' Statement         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) WithNode(GLOBAL_DATA, $3.m_node, $5.m_node, @3.last_column, @3.last_column - @3.first_column),
                                                                                          $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features | WithFeature, $3.m_numConstants + $5.m_numConstants);
-                                          DBG($$.m_node, @1, @4); }
+                                          setStatementLocation($$.m_node, @1, @4); }
 ;
 
 SwitchStatement:
     SWITCH '(' Expr ')' CaseBlock       { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) SwitchNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations,
                                                                                          $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
 ;
 
 SwitchStatement:
     SWITCH '(' Expr ')' CaseBlock       { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) SwitchNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations,
                                                                                          $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
-                                          DBG($$.m_node, @1, @4); }
+                                          setStatementLocation($$.m_node, @1, @4); }
 ;
 
 CaseBlock:
 ;
 
 CaseBlock:
@@ -1092,7 +1099,7 @@ CaseBlock:
 ;
 
 CaseClausesOpt:
 ;
 
 CaseClausesOpt:
-/* nothing */                       { $$.m_node.head = 0; $$.m_node.tail = 0; $$.m_varDeclarations = 0; $$.m_funcDeclarations = 0; $$.m_features = 0; $$.m_numConstants = 0; }
+  /* nothing */                         { $$.m_node.head = 0; $$.m_node.tail = 0; $$.m_varDeclarations = 0; $$.m_funcDeclarations = 0; $$.m_features = 0; $$.m_numConstants = 0; }
   | CaseClauses
 ;
 
   | CaseClauses
 ;
 
@@ -1124,18 +1131,18 @@ DefaultClause:
 
 LabelledStatement:
     IDENT ':' Statement                 { LabelNode* node = new (GLOBAL_DATA) LabelNode(GLOBAL_DATA, *$1, $3.m_node);
 
 LabelledStatement:
     IDENT ':' Statement                 { LabelNode* node = new (GLOBAL_DATA) LabelNode(GLOBAL_DATA, *$1, $3.m_node);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
                                           $$ = createNodeDeclarationInfo<StatementNode*>(node, $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); }
 ;
 
 ThrowStatement:
     THROW Expr ';'                      { ThrowNode* node = new (GLOBAL_DATA) ThrowNode(GLOBAL_DATA, $2.m_node);
                                           $$ = createNodeDeclarationInfo<StatementNode*>(node, $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); }
 ;
 
 ThrowStatement:
     THROW Expr ';'                      { ThrowNode* node = new (GLOBAL_DATA) ThrowNode(GLOBAL_DATA, $2.m_node);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2);
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
+                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); setStatementLocation($$.m_node, @1, @2);
                                         }
   | THROW Expr error                    { ThrowNode* node = new (GLOBAL_DATA) ThrowNode(GLOBAL_DATA, $2.m_node);
                                         }
   | THROW Expr error                    { ThrowNode* node = new (GLOBAL_DATA) ThrowNode(GLOBAL_DATA, $2.m_node);
-                                          SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; 
+                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
+                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); setStatementLocation($$.m_node, @1, @2); AUTO_SEMICOLON; 
                                         }
 ;
 
                                         }
 ;
 
@@ -1145,57 +1152,57 @@ TryStatement:
                                                                                          mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations),
                                                                                          $2.m_features | $4.m_features,
                                                                                          $2.m_numConstants + $4.m_numConstants);
                                                                                          mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations),
                                                                                          $2.m_features | $4.m_features,
                                                                                          $2.m_numConstants + $4.m_numConstants);
-                                          DBG($$.m_node, @1, @2); }
+                                          setStatementLocation($$.m_node, @1, @2); }
   | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, 0),
                                                                                          mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations),
                                                                                          mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations),
                                                                                          $2.m_features | $7.m_features | CatchFeature,
                                                                                          $2.m_numConstants + $7.m_numConstants);
   | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, 0),
                                                                                          mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations),
                                                                                          mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations),
                                                                                          $2.m_features | $7.m_features | CatchFeature,
                                                                                          $2.m_numConstants + $7.m_numConstants);
-                                          DBG($$.m_node, @1, @2); }
+                                          setStatementLocation($$.m_node, @1, @2); }
   | TRY Block CATCH '(' IDENT ')' Block FINALLY Block
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, $9.m_node),
                                                                                          mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations),
                                                                                          mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations),
                                                                                          $2.m_features | $7.m_features | $9.m_features | CatchFeature,
                                                                                          $2.m_numConstants + $7.m_numConstants + $9.m_numConstants);
   | TRY Block CATCH '(' IDENT ')' Block FINALLY Block
                                         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, $9.m_node),
                                                                                          mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations),
                                                                                          mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations),
                                                                                          $2.m_features | $7.m_features | $9.m_features | CatchFeature,
                                                                                          $2.m_numConstants + $7.m_numConstants + $9.m_numConstants);
-                                          DBG($$.m_node, @1, @2); }
+                                          setStatementLocation($$.m_node, @1, @2); }
 ;
 
 DebuggerStatement:
     DEBUGGER ';'                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
 ;
 
 DebuggerStatement:
     DEBUGGER ';'                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
-                                          DBG($$.m_node, @1, @2); }
+                                          setStatementLocation($$.m_node, @1, @2); }
   | DEBUGGER error                      { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
   | DEBUGGER error                      { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
-                                          DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+                                          setStatementLocation($$.m_node, @1, @1); AUTO_SEMICOLON; }
 ;
 
 FunctionDeclaration:
 ;
 
 FunctionDeclaration:
-    FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); DBG($6, @5, @7); $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)); }
+    FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) FuncDeclNode(GLOBAL_DATA, *$2, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line)), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); setStatementLocation($6, @5, @7); $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)->body()); }
   | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
   | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
-      { 
-          $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features | ClosureFeature, 0); 
+      {
+          $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) FuncDeclNode(GLOBAL_DATA, *$2, $7, GLOBAL_DATA->lexer->sourceCode($6, $8, @6.first_line), $4.m_node.head), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features | ClosureFeature, 0);
           if ($4.m_features & ArgumentsFeature)
           if ($4.m_features & ArgumentsFeature)
-              $7->setUsesArguments(); 
-          DBG($7, @6, @8);
-          $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node));
+              $7->setUsesArguments();
+          setStatementLocation($7, @6, @8);
+          $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)->body());
       }
 ;
 
 FunctionExpr:
       }
 ;
 
 FunctionExpr:
-    FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $5, LEXER->sourceCode($4, $6, @4.first_line)), ClosureFeature, 0); DBG($5, @4, @6); }
-    | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE 
-      { 
-          $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $6, LEXER->sourceCode($5, $7, @5.first_line), $3.m_node.head), $3.m_features | ClosureFeature, 0); 
-          if ($3.m_features & ArgumentsFeature) 
+    FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $5, GLOBAL_DATA->lexer->sourceCode($4, $6, @4.first_line)), ClosureFeature, 0); setStatementLocation($5, @4, @6); }
+    | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+      {
+          $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line), $3.m_node.head), $3.m_features | ClosureFeature, 0);
+          if ($3.m_features & ArgumentsFeature)
               $6->setUsesArguments();
               $6->setUsesArguments();
-          DBG($6, @5, @7); 
+          setStatementLocation($6, @5, @7);
       }
       }
-  | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); DBG($6, @5, @7); }
-  | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE 
-      { 
-          $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), $4.m_features | ClosureFeature, 0); 
+  | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, *$2, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); setStatementLocation($6, @5, @7); }
+  | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+      {
+          $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, *$2, $7, GLOBAL_DATA->lexer->sourceCode($6, $8, @6.first_line), $4.m_node.head), $4.m_features | ClosureFeature, 0); 
           if ($4.m_features & ArgumentsFeature)
               $7->setUsesArguments();
           if ($4.m_features & ArgumentsFeature)
               $7->setUsesArguments();
-          DBG($7, @6, @8); 
+          setStatementLocation($7, @6, @8);
       }
 ;
 
       }
 ;
 
@@ -1243,8 +1250,8 @@ Literal_NoNode:
   | FALSETOKEN
   | NUMBER { }
   | STRING { }
   | FALSETOKEN
   | NUMBER { }
   | STRING { }
-  | '/' /* regexp */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; }
-  | DIVEQUAL /* regexp with /= */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; }
+  | '/' /* regexp */ { if (!GLOBAL_DATA->lexer->skipRegExp()) YYABORT; }
+  | DIVEQUAL /* regexp with /= */ { if (!GLOBAL_DATA->lexer->skipRegExp()) YYABORT; }
 ;
 
 Property_NoNode:
 ;
 
 Property_NoNode:
@@ -1826,26 +1833,28 @@ SourceElements_NoNode:
 
 %%
 
 
 %%
 
-static ExpressionNode* makeAssignNode(void* globalPtr, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
+#undef GLOBAL_DATA
+
+static ExpressionNode* makeAssignNode(JSGlobalData* globalData, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
 {
     if (!loc->isLocation())
 {
     if (!loc->isLocation())
-        return new (GLOBAL_DATA) AssignErrorNode(GLOBAL_DATA, loc, op, expr, divot, divot - start, end - divot);
+        return new (globalData) AssignErrorNode(globalData, loc, op, expr, divot, divot - start, end - divot);
 
     if (loc->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(loc);
         if (op == OpEqual) {
 
     if (loc->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(loc);
         if (op == OpEqual) {
-            AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, resolve->identifier(), expr, exprHasAssignments);
-            SET_EXCEPTION_LOCATION(node, start, divot, end);
+            AssignResolveNode* node = new (globalData) AssignResolveNode(globalData, resolve->identifier(), expr, exprHasAssignments);
+            setExceptionLocation(node, start, divot, end);
             return node;
         } else
             return node;
         } else
-            return new (GLOBAL_DATA) ReadModifyResolveNode(GLOBAL_DATA, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+            return new (globalData) ReadModifyResolveNode(globalData, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
     }
     if (loc->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
         if (op == OpEqual)
     }
     if (loc->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
         if (op == OpEqual)
-            return new (GLOBAL_DATA) AssignBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot());
+            return new (globalData) AssignBracketNode(globalData, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot());
         else {
         else {
-            ReadModifyBracketNode* node = new (GLOBAL_DATA) ReadModifyBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot);
+            ReadModifyBracketNode* node = new (globalData) ReadModifyBracketNode(globalData, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot);
             node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
             return node;
         }
             node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
             return node;
         }
@@ -1853,117 +1862,117 @@ static ExpressionNode* makeAssignNode(void* globalPtr, ExpressionNode* loc, Oper
     ASSERT(loc->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
     if (op == OpEqual)
     ASSERT(loc->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
     if (op == OpEqual)
-        return new (GLOBAL_DATA) AssignDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot());
+        return new (globalData) AssignDotNode(globalData, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot());
 
 
-    ReadModifyDotNode* node = new (GLOBAL_DATA) ReadModifyDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+    ReadModifyDotNode* node = new (globalData) ReadModifyDotNode(globalData, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return node;
 }
 
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return node;
 }
 
-static ExpressionNode* makePrefixNode(void* globalPtr, ExpressionNode* expr, Operator op, int start, int divot, int end)
+static ExpressionNode* makePrefixNode(JSGlobalData* globalData, ExpressionNode* expr, Operator op, int start, int divot, int end)
 {
     if (!expr->isLocation())
 {
     if (!expr->isLocation())
-        return new (GLOBAL_DATA) PrefixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot);
+        return new (globalData) PrefixErrorNode(globalData, expr, op, divot, divot - start, end - divot);
     
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
     
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (GLOBAL_DATA) PrefixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot);
+        return new (globalData) PrefixResolveNode(globalData, resolve->identifier(), op, divot, divot - start, end - divot);
     }
     if (expr->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
     }
     if (expr->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
-        PrefixBracketNode* node = new (GLOBAL_DATA) PrefixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
+        PrefixBracketNode* node = new (globalData) PrefixBracketNode(globalData, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
         node->setSubexpressionInfo(bracket->divot(), bracket->startOffset());
         return node;
     }
     ASSERT(expr->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
         node->setSubexpressionInfo(bracket->divot(), bracket->startOffset());
         return node;
     }
     ASSERT(expr->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
-    PrefixDotNode* node = new (GLOBAL_DATA) PrefixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
+    PrefixDotNode* node = new (globalData) PrefixDotNode(globalData, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
     node->setSubexpressionInfo(dot->divot(), dot->startOffset());
     return node;
 }
 
     node->setSubexpressionInfo(dot->divot(), dot->startOffset());
     return node;
 }
 
-static ExpressionNode* makePostfixNode(void* globalPtr, ExpressionNode* expr, Operator op, int start, int divot, int end)
+static ExpressionNode* makePostfixNode(JSGlobalData* globalData, ExpressionNode* expr, Operator op, int start, int divot, int end)
 { 
     if (!expr->isLocation())
 { 
     if (!expr->isLocation())
-        return new (GLOBAL_DATA) PostfixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot);
+        return new (globalData) PostfixErrorNode(globalData, expr, op, divot, divot - start, end - divot);
     
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
     
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (GLOBAL_DATA) PostfixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot);
+        return new (globalData) PostfixResolveNode(globalData, resolve->identifier(), op, divot, divot - start, end - divot);
     }
     if (expr->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
     }
     if (expr->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
-        PostfixBracketNode* node = new (GLOBAL_DATA) PostfixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
+        PostfixBracketNode* node = new (globalData) PostfixBracketNode(globalData, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
         node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
         return node;
         
     }
     ASSERT(expr->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
         node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
         return node;
         
     }
     ASSERT(expr->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
-    PostfixDotNode* node = new (GLOBAL_DATA) PostfixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
+    PostfixDotNode* node = new (globalData) PostfixDotNode(globalData, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return node;
 }
 
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return node;
 }
 
-static ExpressionNodeInfo makeFunctionCallNode(void* globalPtr, ExpressionNodeInfo func, ArgumentsNodeInfo args, int start, int divot, int end)
+static ExpressionNodeInfo makeFunctionCallNode(JSGlobalData* globalData, ExpressionNodeInfo func, ArgumentsNodeInfo args, int start, int divot, int end)
 {
     CodeFeatures features = func.m_features | args.m_features;
     int numConstants = func.m_numConstants + args.m_numConstants;
     if (!func.m_node->isLocation())
 {
     CodeFeatures features = func.m_features | args.m_features;
     int numConstants = func.m_numConstants + args.m_numConstants;
     if (!func.m_node->isLocation())
-        return createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) FunctionCallValueNode(GLOBAL_DATA, func.m_node, args.m_node, divot, divot - start, end - divot), features, numConstants);
+        return createNodeInfo<ExpressionNode*>(new (globalData) FunctionCallValueNode(globalData, func.m_node, args.m_node, divot, divot - start, end - divot), features, numConstants);
     if (func.m_node->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(func.m_node);
         const Identifier& identifier = resolve->identifier();
     if (func.m_node->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(func.m_node);
         const Identifier& identifier = resolve->identifier();
-        if (identifier == GLOBAL_DATA->propertyNames->eval)
-            return createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EvalFunctionCallNode(GLOBAL_DATA, args.m_node, divot, divot - start, end - divot), EvalFeature | features, numConstants);
-        return createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) FunctionCallResolveNode(GLOBAL_DATA, identifier, args.m_node, divot, divot - start, end - divot), features, numConstants);
+        if (identifier == globalData->propertyNames->eval)
+            return createNodeInfo<ExpressionNode*>(new (globalData) EvalFunctionCallNode(globalData, args.m_node, divot, divot - start, end - divot), EvalFeature | features, numConstants);
+        return createNodeInfo<ExpressionNode*>(new (globalData) FunctionCallResolveNode(globalData, identifier, args.m_node, divot, divot - start, end - divot), features, numConstants);
     }
     if (func.m_node->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func.m_node);
     }
     if (func.m_node->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func.m_node);
-        FunctionCallBracketNode* node = new (GLOBAL_DATA) FunctionCallBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), args.m_node, divot, divot - start, end - divot);
+        FunctionCallBracketNode* node = new (globalData) FunctionCallBracketNode(globalData, bracket->base(), bracket->subscript(), args.m_node, divot, divot - start, end - divot);
         node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
         return createNodeInfo<ExpressionNode*>(node, features, numConstants);
     }
     ASSERT(func.m_node->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(func.m_node);
     FunctionCallDotNode* node;
         node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
         return createNodeInfo<ExpressionNode*>(node, features, numConstants);
     }
     ASSERT(func.m_node->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(func.m_node);
     FunctionCallDotNode* node;
-    if (dot->identifier() == GLOBAL_DATA->propertyNames->call)
-        node = new (GLOBAL_DATA) CallFunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
-    else if (dot->identifier() == GLOBAL_DATA->propertyNames->apply)
-        node = new (GLOBAL_DATA) ApplyFunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
+    if (dot->identifier() == globalData->propertyNames->call)
+        node = new (globalData) CallFunctionCallDotNode(globalData, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
+    else if (dot->identifier() == globalData->propertyNames->apply)
+        node = new (globalData) ApplyFunctionCallDotNode(globalData, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
     else
     else
-        node = new (GLOBAL_DATA) FunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
+        node = new (globalData) FunctionCallDotNode(globalData, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return createNodeInfo<ExpressionNode*>(node, features, numConstants);
 }
 
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return createNodeInfo<ExpressionNode*>(node, features, numConstants);
 }
 
-static ExpressionNode* makeTypeOfNode(void* globalPtr, ExpressionNode* expr)
+static ExpressionNode* makeTypeOfNode(JSGlobalData* globalData, ExpressionNode* expr)
 {
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
 {
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (GLOBAL_DATA) TypeOfResolveNode(GLOBAL_DATA, resolve->identifier());
+        return new (globalData) TypeOfResolveNode(globalData, resolve->identifier());
     }
     }
-    return new (GLOBAL_DATA) TypeOfValueNode(GLOBAL_DATA, expr);
+    return new (globalData) TypeOfValueNode(globalData, expr);
 }
 
 }
 
-static ExpressionNode* makeDeleteNode(void* globalPtr, ExpressionNode* expr, int start, int divot, int end)
+static ExpressionNode* makeDeleteNode(JSGlobalData* globalData, ExpressionNode* expr, int start, int divot, int end)
 {
     if (!expr->isLocation())
 {
     if (!expr->isLocation())
-        return new (GLOBAL_DATA) DeleteValueNode(GLOBAL_DATA, expr);
+        return new (globalData) DeleteValueNode(globalData, expr);
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (GLOBAL_DATA) DeleteResolveNode(GLOBAL_DATA, resolve->identifier(), divot, divot - start, end - divot);
+        return new (globalData) DeleteResolveNode(globalData, resolve->identifier(), divot, divot - start, end - divot);
     }
     if (expr->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
     }
     if (expr->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
-        return new (GLOBAL_DATA) DeleteBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), divot, divot - start, end - divot);
+        return new (globalData) DeleteBracketNode(globalData, bracket->base(), bracket->subscript(), divot, divot - start, end - divot);
     }
     ASSERT(expr->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
     }
     ASSERT(expr->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
-    return new (GLOBAL_DATA) DeleteDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), divot, divot - start, end - divot);
+    return new (globalData) DeleteDotNode(globalData, dot->base(), dot->identifier(), divot, divot - start, end - divot);
 }
 
 }
 
-static PropertyNode* makeGetterOrSetterPropertyNode(void* globalPtr, const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body, const SourceCode& source)
+static PropertyNode* makeGetterOrSetterPropertyNode(JSGlobalData* globalData, const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body, const SourceCode& source)
 {
     PropertyNode::Type type;
     if (getOrSet == "get")
 {
     PropertyNode::Type type;
     if (getOrSet == "get")
@@ -1972,10 +1981,10 @@ static PropertyNode* makeGetterOrSetterPropertyNode(void* globalPtr, const Ident
         type = PropertyNode::Setter;
     else
         return 0;
         type = PropertyNode::Setter;
     else
         return 0;
-    return new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, name, new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, body, source, params), type);
+    return new (globalData) PropertyNode(globalData, name, new (globalData) FuncExprNode(globalData, globalData->propertyNames->nullIdentifier, body, source, params), type);
 }
 
 }
 
-static ExpressionNode* makeNegateNode(void* globalPtr, ExpressionNode* n)
+static ExpressionNode* makeNegateNode(JSGlobalData* globalData, ExpressionNode* n)
 {
     if (n->isNumber()) {
         NumberNode* number = static_cast<NumberNode*>(n);
 {
     if (n->isNumber()) {
         NumberNode* number = static_cast<NumberNode*>(n);
@@ -1986,92 +1995,92 @@ static ExpressionNode* makeNegateNode(void* globalPtr, ExpressionNode* n)
         }
     }
 
         }
     }
 
-    return new (GLOBAL_DATA) NegateNode(GLOBAL_DATA, n);
+    return new (globalData) NegateNode(globalData, n);
 }
 
 }
 
-static NumberNode* makeNumberNode(void* globalPtr, double d)
+static NumberNode* makeNumberNode(JSGlobalData* globalData, double d)
 {
 {
-    return new (GLOBAL_DATA) NumberNode(GLOBAL_DATA, d);
+    return new (globalData) NumberNode(globalData, d);
 }
 
 }
 
-static ExpressionNode* makeBitwiseNotNode(void* globalPtr, ExpressionNode* expr)
+static ExpressionNode* makeBitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr)
 {
     if (expr->isNumber())
 {
     if (expr->isNumber())
-        return makeNumberNode(globalPtr, ~toInt32(static_cast<NumberNode*>(expr)->value()));
-    return new (GLOBAL_DATA) BitwiseNotNode(GLOBAL_DATA, expr);
+        return makeNumberNode(globalData, ~toInt32(static_cast<NumberNode*>(expr)->value()));
+    return new (globalData) BitwiseNotNode(globalData, expr);
 }
 
 }
 
-static ExpressionNode* makeMultNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+static ExpressionNode* makeMultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
 
     if (expr1->isNumber() && expr2->isNumber())
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
 
     if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value());
+        return makeNumberNode(globalData, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value());
 
     if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1)
 
     if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1)
-        return new (GLOBAL_DATA) UnaryPlusNode(GLOBAL_DATA, expr2);
+        return new (globalData) UnaryPlusNode(globalData, expr2);
 
     if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
 
     if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
-        return new (GLOBAL_DATA) UnaryPlusNode(GLOBAL_DATA, expr1);
+        return new (globalData) UnaryPlusNode(globalData, expr1);
 
 
-    return new (GLOBAL_DATA) MultNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+    return new (globalData) MultNode(globalData, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-static ExpressionNode* makeDivNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+static ExpressionNode* makeDivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
 
     if (expr1->isNumber() && expr2->isNumber())
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
 
     if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value());
-    return new (GLOBAL_DATA) DivNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+        return makeNumberNode(globalData, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value());
+    return new (globalData) DivNode(globalData, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-static ExpressionNode* makeAddNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+static ExpressionNode* makeAddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     if (expr1->isNumber() && expr2->isNumber())
 {
     if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value());
-    return new (GLOBAL_DATA) AddNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+        return makeNumberNode(globalData, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value());
+    return new (globalData) AddNode(globalData, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-static ExpressionNode* makeSubNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+static ExpressionNode* makeSubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
 
     if (expr1->isNumber() && expr2->isNumber())
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
 
     if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value());
-    return new (GLOBAL_DATA) SubNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+        return makeNumberNode(globalData, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value());
+    return new (globalData) SubNode(globalData, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-static ExpressionNode* makeLeftShiftNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+static ExpressionNode* makeLeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     if (expr1->isNumber() && expr2->isNumber())
 {
     if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalPtr, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
-    return new (GLOBAL_DATA) LeftShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+        return makeNumberNode(globalData, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+    return new (globalData) LeftShiftNode(globalData, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-static ExpressionNode* makeRightShiftNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+static ExpressionNode* makeRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     if (expr1->isNumber() && expr2->isNumber())
 {
     if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalPtr, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
-    return new (GLOBAL_DATA) RightShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+        return makeNumberNode(globalData, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+    return new (globalData) RightShiftNode(globalData, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-/* called by yyparse on error */
-int yyerror(const char *)
+// Called by yyparse on error.
+int yyerror(const char*)
 {
     return 1;
 }
 
 {
     return 1;
 }
 
-/* may we automatically insert a semicolon ? */
+// May we automatically insert a semicolon?
 static bool allowAutomaticSemicolon(Lexer& lexer, int yychar)
 {
     return yychar == CLOSEBRACE || yychar == 0 || lexer.prevTerminator();
 }
 
 static bool allowAutomaticSemicolon(Lexer& lexer, int yychar)
 {
     return yychar == CLOSEBRACE || yychar == 0 || lexer.prevTerminator();
 }
 
-static ExpressionNode* combineCommaNodes(void* globalPtr, ExpressionNode* list, ExpressionNode* init)
+static ExpressionNode* combineCommaNodes(JSGlobalData* globalData, ExpressionNode* list, ExpressionNode* init)
 {
     if (!list)
         return init;
 {
     if (!list)
         return init;
@@ -2079,17 +2088,15 @@ static ExpressionNode* combineCommaNodes(void* globalPtr, ExpressionNode* list,
         static_cast<CommaNode*>(list)->append(init);
         return list;
     }
         static_cast<CommaNode*>(list)->append(init);
         return list;
     }
-    return new (GLOBAL_DATA) CommaNode(GLOBAL_DATA, list, init);
+    return new (globalData) CommaNode(globalData, list, init);
 }
 
 // We turn variable declarations into either assignments or empty
 // statements (which later get stripped out), because the actual
 // declaration work is hoisted up to the start of the function body
 }
 
 // We turn variable declarations into either assignments or empty
 // statements (which later get stripped out), because the actual
 // declaration work is hoisted up to the start of the function body
-static StatementNode* makeVarStatementNode(void* globalPtr, ExpressionNode* expr)
+static StatementNode* makeVarStatementNode(JSGlobalData* globalData, ExpressionNode* expr)
 {
     if (!expr)
 {
     if (!expr)
-        return new (GLOBAL_DATA) EmptyStatementNode(GLOBAL_DATA);
-    return new (GLOBAL_DATA) VarStatementNode(GLOBAL_DATA, expr);
+        return new (globalData) EmptyStatementNode(globalData);
+    return new (globalData) VarStatementNode(globalData, expr);
 }
 }
-
-#undef GLOBAL_DATA
index 8e89c18a9ee9ff0f7ef90279ad0f4db5885aa73b..83f56bd244bb5f0e9c172efce957e99b8893787e 100644 (file)
@@ -39,19 +39,10 @@ using namespace Unicode;
 // We can't specify the namespace in yacc's C output, so do it here instead.
 using namespace JSC;
 
 // We can't specify the namespace in yacc's C output, so do it here instead.
 using namespace JSC;
 
-#ifndef KDE_USE_FINAL
 #include "Grammar.h"
 #include "Grammar.h"
-#endif
-
 #include "Lookup.h"
 #include "Lexer.lut.h"
 
 #include "Lookup.h"
 #include "Lexer.lut.h"
 
-// A bridge for yacc from the C world to the C++ world.
-int jscyylex(void* lvalp, void* llocp, void* globalData)
-{
-    return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
-}
-
 namespace JSC {
 
 static const UChar byteOrderMark = 0xFEFF;
 namespace JSC {
 
 static const UChar byteOrderMark = 0xFEFF;
@@ -141,8 +132,10 @@ ALWAYS_INLINE void Lexer::shift4()
     m_code += 4;
 }
 
     m_code += 4;
 }
 
-void Lexer::setCode(const SourceCode& source)
+void Lexer::setCode(const SourceCode& source, ParserArena& arena)
 {
 {
+    m_arena = &arena.identifierArena();
+
     m_lineNumber = source.firstLine();
     m_delimited = false;
     m_lastToken = -1;
     m_lineNumber = source.firstLine();
     m_delimited = false;
     m_lastToken = -1;
@@ -204,10 +197,9 @@ void Lexer::shiftLineTerminator()
     ++m_lineNumber;
 }
 
     ++m_lineNumber;
 }
 
-ALWAYS_INLINE Identifier* Lexer::makeIdentifier(const UChar* characters, size_t length)
+ALWAYS_INLINE const Identifier* Lexer::makeIdentifier(const UChar* characters, size_t length)
 {
 {
-    m_identifiers.append(Identifier(m_globalData, characters, length));
-    return &m_identifiers.last();
+    return &m_arena->makeIdentifier(m_globalData, characters, length);
 }
 
 inline bool Lexer::lastTokenWasRestrKeyword() const
 }
 
 inline bool Lexer::lastTokenWasRestrKeyword() const
@@ -647,6 +639,8 @@ inStringEscapeSequence:
         shiftLineTerminator();
         goto inString;
     }
         shiftLineTerminator();
         goto inString;
     }
+    if (m_current == -1)
+        goto returnError;
     record16(singleEscape(m_current));
     shift1();
     goto inString;
     record16(singleEscape(m_current));
     shift1();
     goto inString;
@@ -908,48 +902,110 @@ returnError:
     return -1;
 }
 
     return -1;
 }
 
-bool Lexer::scanRegExp()
+bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix)
 {
     ASSERT(m_buffer16.isEmpty());
 
     bool lastWasEscape = false;
     bool inBrackets = false;
 
 {
     ASSERT(m_buffer16.isEmpty());
 
     bool lastWasEscape = false;
     bool inBrackets = false;
 
+    if (patternPrefix) {
+        ASSERT(!isLineTerminator(patternPrefix));
+        ASSERT(patternPrefix != '/');
+        ASSERT(patternPrefix != '[');
+        record16(patternPrefix);
+    }
+
     while (true) {
     while (true) {
-        if (isLineTerminator(m_current) || m_current == -1)
-            return false;
-        if (m_current != '/' || lastWasEscape || inBrackets) {
-            // keep track of '[' and ']'
-            if (!lastWasEscape) {
-                if (m_current == '[' && !inBrackets)
-                    inBrackets = true;
-                if (m_current == ']' && inBrackets)
-                    inBrackets = false;
-            }
-            record16(m_current);
-            lastWasEscape = !lastWasEscape && m_current == '\\';
-        } else { // end of regexp
-            m_pattern = UString(m_buffer16);
+        int current = m_current;
+
+        if (isLineTerminator(current) || current == -1) {
             m_buffer16.resize(0);
             m_buffer16.resize(0);
-            shift1();
-            break;
+            return false;
         }
         }
+
         shift1();
         shift1();
+
+        if (current == '/' && !lastWasEscape && !inBrackets)
+            break;
+
+        record16(current);
+
+        if (lastWasEscape) {
+            lastWasEscape = false;
+            continue;
+        }
+
+        switch (current) {
+        case '[':
+            inBrackets = true;
+            break;
+        case ']':
+            inBrackets = false;
+            break;
+        case '\\':
+            lastWasEscape = true;
+            break;
+        }
     }
 
     }
 
+    pattern = makeIdentifier(m_buffer16.data(), m_buffer16.size());
+    m_buffer16.resize(0);
+
     while (isIdentPart(m_current)) {
         record16(m_current);
         shift1();
     }
     while (isIdentPart(m_current)) {
         record16(m_current);
         shift1();
     }
-    m_flags = UString(m_buffer16);
+
+    flags = makeIdentifier(m_buffer16.data(), m_buffer16.size());
     m_buffer16.resize(0);
 
     return true;
 }
 
     m_buffer16.resize(0);
 
     return true;
 }
 
+bool Lexer::skipRegExp()
+{
+    bool lastWasEscape = false;
+    bool inBrackets = false;
+
+    while (true) {
+        int current = m_current;
+
+        if (isLineTerminator(current) || current == -1)
+            return false;
+
+        shift1();
+
+        if (current == '/' && !lastWasEscape && !inBrackets)
+            break;
+
+        if (lastWasEscape) {
+            lastWasEscape = false;
+            continue;
+        }
+
+        switch (current) {
+        case '[':
+            inBrackets = true;
+            break;
+        case ']':
+            inBrackets = false;
+            break;
+        case '\\':
+            lastWasEscape = true;
+            break;
+        }
+    }
+
+    while (isIdentPart(m_current))
+        shift1();
+
+    return true;
+}
+
 void Lexer::clear()
 {
 void Lexer::clear()
 {
-    m_identifiers.clear();
+    m_arena = 0;
     m_codeWithoutBOMs.clear();
 
     Vector<char> newBuffer8;
     m_codeWithoutBOMs.clear();
 
     Vector<char> newBuffer8;
@@ -961,9 +1017,6 @@ void Lexer::clear()
     m_buffer16.swap(newBuffer16);
 
     m_isReparsing = false;
     m_buffer16.swap(newBuffer16);
 
     m_isReparsing = false;
-
-    m_pattern = UString();
-    m_flags = UString();
 }
 
 SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine)
 }
 
 SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine)
index 0e1b6188e0f28b19b572affb97ebcc1a631f1c34..c76696cf3b3fa4e6872e70af753c185a5e21db1f 100644 (file)
@@ -23,6 +23,7 @@
 #define Lexer_h
 
 #include "Lookup.h"
 #define Lexer_h
 
 #include "Lookup.h"
+#include "ParserArena.h"
 #include "SourceCode.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/SegmentedVector.h>
 #include "SourceCode.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/SegmentedVector.h>
@@ -33,7 +34,7 @@ namespace JSC {
 
     class RegExp;
 
 
     class RegExp;
 
-    class Lexer : Noncopyable {
+    class Lexer : public Noncopyable {
     public:
         // Character manipulation functions.
         static bool isWhiteSpace(int character);
     public:
         // Character manipulation functions.
         static bool isWhiteSpace(int character);
@@ -42,7 +43,7 @@ namespace JSC {
         static UChar convertUnicode(int c1, int c2, int c3, int c4);
 
         // Functions to set up parsing.
         static UChar convertUnicode(int c1, int c2, int c3, int c4);
 
         // Functions to set up parsing.
-        void setCode(const SourceCode&);
+        void setCode(const SourceCode&, ParserArena&);
         void setIsReparsing() { m_isReparsing = true; }
 
         // Functions for the parser itself.
         void setIsReparsing() { m_isReparsing = true; }
 
         // Functions for the parser itself.
@@ -50,9 +51,8 @@ namespace JSC {
         int lineNumber() const { return m_lineNumber; }
         bool prevTerminator() const { return m_terminator; }
         SourceCode sourceCode(int openBrace, int closeBrace, int firstLine);
         int lineNumber() const { return m_lineNumber; }
         bool prevTerminator() const { return m_terminator; }
         SourceCode sourceCode(int openBrace, int closeBrace, int firstLine);
-        bool scanRegExp();
-        const UString& pattern() const { return m_pattern; }
-        const UString& flags() const { return m_flags; }
+        bool scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix = 0);
+        bool skipRegExp();
 
         // Functions for use after parsing.
         bool sawError() const { return m_error; }
 
         // Functions for use after parsing.
         bool sawError() const { return m_error; }
@@ -79,12 +79,11 @@ namespace JSC {
         int currentOffset() const;
         const UChar* currentCharacter() const;
 
         int currentOffset() const;
         const UChar* currentCharacter() const;
 
-        JSC::Identifier* makeIdentifier(const UChar* buffer, size_t length);
+        const Identifier* makeIdentifier(const UChar* characters, size_t length);
 
         bool lastTokenWasRestrKeyword() const;
 
         static const size_t initialReadBufferCapacity = 32;
 
         bool lastTokenWasRestrKeyword() const;
 
         static const size_t initialReadBufferCapacity = 32;
-        static const size_t initialIdentifierTableCapacity = 64;
 
         int m_lineNumber;
 
 
         int m_lineNumber;
 
@@ -108,13 +107,10 @@ namespace JSC {
         int m_next2;
         int m_next3;
         
         int m_next2;
         int m_next3;
         
-        WTF::SegmentedVector<JSC::Identifier, initialIdentifierTableCapacity> m_identifiers;
+        IdentifierArena* m_arena;
 
         JSGlobalData* m_globalData;
 
 
         JSGlobalData* m_globalData;
 
-        UString m_pattern;
-        UString m_flags;
-
         const HashTable m_keywordTable;
 
         Vector<UChar> m_codeWithoutBOMs;
         const HashTable m_keywordTable;
 
         Vector<UChar> m_codeWithoutBOMs;
@@ -140,6 +136,12 @@ namespace JSC {
         return (convertHex(c1, c2) << 8) | convertHex(c3, c4);
     }
 
         return (convertHex(c1, c2) << 8) | convertHex(c3, c4);
     }
 
+    // A bridge for yacc from the C world to the C++ world.
+    inline int jscyylex(void* lvalp, void* llocp, void* globalData)
+    {
+        return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
+    }
+
 } // namespace JSC
 
 #endif // Lexer_h
 } // namespace JSC
 
 #endif // Lexer_h
index d17da69cbba24428cf78b3a48dec9a1b7e86bdd7..dd3b9816f657f77d8514c5096c28ecf8ed31ffd1 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    inline void* ParserArenaDeletable::operator new(size_t size, JSGlobalData* globalData)
+    inline void* ParserArenaFreeable::operator new(size_t size, JSGlobalData* globalData)
     {
     {
-        ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(fastMalloc(size));
-        globalData->parser->arena().deleteWithArena(deletable);
-        return deletable;
+        return globalData->parser->arena().allocateFreeable(size);
     }
 
     }
 
-    inline void* ParserArenaDeletable::operator new(size_t size)
+    inline void* ParserArenaDeletable::operator new(size_t size, JSGlobalData* globalData)
     {
     {
-        return fastMalloc(size);
+        return globalData->parser->arena().allocateDeletable(size);
     }
 
     inline ParserArenaRefCounted::ParserArenaRefCounted(JSGlobalData* globalData)
     }
 
     inline ParserArenaRefCounted::ParserArenaRefCounted(JSGlobalData* globalData)
@@ -72,19 +70,19 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline NumberNode::NumberNode(JSGlobalData* globalData, double v)
+    inline NumberNode::NumberNode(JSGlobalData* globalData, double value)
         : ExpressionNode(globalData, ResultType::numberType())
         : ExpressionNode(globalData, ResultType::numberType())
-        , m_double(v)
+        , m_value(value)
     {
     }
 
     {
     }
 
-    inline StringNode::StringNode(JSGlobalData* globalData, const Identifier& v)
+    inline StringNode::StringNode(JSGlobalData* globalData, const Identifier& value)
         : ExpressionNode(globalData, ResultType::stringType())
         : ExpressionNode(globalData, ResultType::stringType())
-        , m_value(v)
+        , m_value(value)
     {
     }
 
     {
     }
 
-    inline RegExpNode::RegExpNode(JSGlobalData* globalData, const UString& pattern, const UString& flags)
+    inline RegExpNode::RegExpNode(JSGlobalData* globalData, const Identifier& pattern, const Identifier& flags)
         : ExpressionNode(globalData)
         , m_pattern(pattern)
         , m_flags(flags)
         : ExpressionNode(globalData)
         , m_pattern(pattern)
         , m_flags(flags)
@@ -149,6 +147,13 @@ namespace JSC {
     {
     }
 
     {
     }
 
+    inline PropertyNode::PropertyNode(JSGlobalData* globalData, double name, ExpressionNode* assign, Type type)
+        : m_name(globalData->parser->arena().identifierArena().makeNumericIdentifier(globalData, name))
+        , m_assign(assign)
+        , m_type(type)
+    {
+    }
+
     inline PropertyListNode::PropertyListNode(JSGlobalData* globalData, PropertyNode* node)
         : Node(globalData)
         , m_node(node)
     inline PropertyListNode::PropertyListNode(JSGlobalData* globalData, PropertyNode* node)
         : Node(globalData)
         , m_node(node)
@@ -736,6 +741,7 @@ namespace JSC {
 
     inline ContinueNode::ContinueNode(JSGlobalData* globalData)
         : StatementNode(globalData)
 
     inline ContinueNode::ContinueNode(JSGlobalData* globalData)
         : StatementNode(globalData)
+        , m_ident(globalData->propertyNames->nullIdentifier)
     {
     }
 
     {
     }
 
@@ -747,6 +753,7 @@ namespace JSC {
     
     inline BreakNode::BreakNode(JSGlobalData* globalData)
         : StatementNode(globalData)
     
     inline BreakNode::BreakNode(JSGlobalData* globalData)
         : StatementNode(globalData)
+        , m_ident(globalData->propertyNames->nullIdentifier)
     {
     }
 
     {
     }
 
@@ -809,32 +816,22 @@ namespace JSC {
 
     inline FuncExprNode::FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter)
         : ExpressionNode(globalData)
 
     inline FuncExprNode::FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter)
         : ExpressionNode(globalData)
-        , ParserArenaRefCounted(globalData)
-        , m_ident(ident)
         , m_body(body)
     {
         , m_body(body)
     {
-        m_body->finishParsing(source, parameter);
+        m_body->finishParsing(source, parameter, ident);
     }
 
     inline FuncDeclNode::FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter)
         : StatementNode(globalData)
     }
 
     inline FuncDeclNode::FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter)
         : StatementNode(globalData)
-        , ParserArenaRefCounted(globalData)
-        , m_ident(ident)
         , m_body(body)
     {
         , m_body(body)
     {
-        m_body->finishParsing(source, parameter);
-    }
-
-    inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr)
-        : m_expr(expr)
-    {
+        m_body->finishParsing(source, parameter, ident);
     }
 
     }
 
-    inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr, SourceElements* children)
+    inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr, SourceElements* statements)
         : m_expr(expr)
         : m_expr(expr)
+        , m_statements(statements)
     {
     {
-        if (children)
-            children->releaseContentsIntoVector(m_children);
     }
 
     inline ClauseListNode::ClauseListNode(JSGlobalData*, CaseClauseNode* clause)
     }
 
     inline ClauseListNode::ClauseListNode(JSGlobalData*, CaseClauseNode* clause)
@@ -872,15 +869,15 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
+    inline BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* statements)
         : StatementNode(globalData)
         : StatementNode(globalData)
+        , m_statements(statements)
     {
     {
-        if (children)
-            children->releaseContentsIntoVector(m_children);
     }
 
     inline ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
         : StatementNode(globalData)
     }
 
     inline ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
         : StatementNode(globalData)
+        , m_ident(globalData->propertyNames->nullIdentifier)
         , m_init(0)
         , m_lexpr(l)
         , m_expr(expr)
         , m_init(0)
         , m_lexpr(l)
         , m_expr(expr)
index 65de89c27b30d5dece001b158b78b4f8d1cae9b0..4b97e9aadb9e2e2c624e422447053d833e910070 100644 (file)
@@ -49,1784 +49,41 @@ using namespace WTF;
 
 namespace JSC {
 
 
 namespace JSC {
 
-static void substitute(UString& string, const UString& substring);
 
 
-// ------------------------------ ThrowableExpressionData --------------------------------
-
-static void substitute(UString& string, const UString& substring)
-{
-    int position = string.find("%s");
-    ASSERT(position != -1);
-    UString newString = string.substr(0, position);
-    newString.append(substring);
-    newString.append(string.substr(position + 2));
-    string = newString;
-}
-
-RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg)
-{
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg));
-    generator.emitThrow(exception);
-    return exception;
-}
-
-RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
-{
-    UString message = msg;
-    substitute(message, label.ustring());
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), message));
-    generator.emitThrow(exception);
-    return exception;
-}
-
-// ------------------------------ StatementNode --------------------------------
-
-void StatementNode::setLoc(int firstLine, int lastLine)
-{
-    m_line = firstLine;
-    m_lastLine = lastLine;
-}
-
-// ------------------------------ SourceElements --------------------------------
-
-void SourceElements::append(StatementNode* statement)
-{
-    if (statement->isEmptyStatement())
-        return;
-    m_statements.append(statement);
-}
-
-// ------------------------------ NullNode -------------------------------------
-
-RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (dst == generator.ignoredResult())
-        return 0;
-    return generator.emitLoad(dst, jsNull());
-}
-
-// ------------------------------ BooleanNode ----------------------------------
-
-RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (dst == generator.ignoredResult())
-        return 0;
-    return generator.emitLoad(dst, m_value);
-}
-
-// ------------------------------ NumberNode -----------------------------------
-
-RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (dst == generator.ignoredResult())
-        return 0;
-    return generator.emitLoad(dst, m_double);
-}
-
-// ------------------------------ StringNode -----------------------------------
-
-RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (dst == generator.ignoredResult())
-        return 0;
-    return generator.emitLoad(dst, m_value);
-}
-
-// ------------------------------ RegExpNode -----------------------------------
-
-RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags);
-    if (!regExp->isValid())
-        return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
-    if (dst == generator.ignoredResult())
-        return 0;
-    return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
-}
-
-// ------------------------------ ThisNode -------------------------------------
-
-RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (dst == generator.ignoredResult())
-        return 0;
-    return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
-}
-
-// ------------------------------ ResolveNode ----------------------------------
-
-bool ResolveNode::isPure(BytecodeGenerator& generator) const
-{
-    return generator.isLocal(m_ident);
-}
-
-RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (RegisterID* local = generator.registerFor(m_ident)) {
-        if (dst == generator.ignoredResult())
-            return 0;
-        return generator.moveToDestinationIfNeeded(dst, local);
-    }
-    
-    generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
-    return generator.emitResolve(generator.finalDestination(dst), m_ident);
-}
-
-// ------------------------------ ArrayNode ------------------------------------
-
-RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    // FIXME: Should we put all of this code into emitNewArray?
-
-    unsigned length = 0;
-    ElementNode* firstPutElement;
-    for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
-        if (firstPutElement->elision())
-            break;
-        ++length;
-    }
-
-    if (!firstPutElement && !m_elision)
-        return generator.emitNewArray(generator.finalDestination(dst), m_element);
-
-    RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element);
-
-    for (ElementNode* n = firstPutElement; n; n = n->next()) {
-        RegisterID* value = generator.emitNode(n->value());
-        length += n->elision();
-        generator.emitPutByIndex(array.get(), length++, value);
-    }
-
-    if (m_elision) {
-        RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length));
-        generator.emitPutById(array.get(), generator.propertyNames().length, value);
-    }
-
-    return generator.moveToDestinationIfNeeded(dst, array.get());
-}
-
-bool ArrayNode::isSimpleArray() const
-{
-    if (m_elision || m_optional)
-        return false;
-    for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
-        if (ptr->elision())
-            return false;
-    }
-    return true;
-}
-
-ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const
-{
-    ASSERT(!m_elision && !m_optional);
-    ElementNode* ptr = m_element;
-    if (!ptr)
-        return 0;
-    ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value());
-    ArgumentListNode* tail = head;
-    ptr = ptr->next();
-    for (; ptr; ptr = ptr->next()) {
-        ASSERT(!ptr->elision());
-        tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value());
-    }
-    return head;
-}
-
-// ------------------------------ ObjectLiteralNode ----------------------------
-
-RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-     if (!m_list) {
-         if (dst == generator.ignoredResult())
-             return 0;
-         return generator.emitNewObject(generator.finalDestination(dst));
-     }
-     return generator.emitNode(dst, m_list);
-}
-
-// ------------------------------ PropertyListNode -----------------------------
-
-RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> newObj = generator.tempDestination(dst);
-    
-    generator.emitNewObject(newObj.get());
-    
-    for (PropertyListNode* p = this; p; p = p->m_next) {
-        RegisterID* value = generator.emitNode(p->m_node->m_assign);
-        
-        switch (p->m_node->m_type) {
-            case PropertyNode::Constant: {
-                generator.emitPutById(newObj.get(), p->m_node->name(), value);
-                break;
-            }
-            case PropertyNode::Getter: {
-                generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
-                break;
-            }
-            case PropertyNode::Setter: {
-                generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
-                break;
-            }
-            default:
-                ASSERT_NOT_REACHED();
-        }
-    }
-    
-    return generator.moveToDestinationIfNeeded(dst, newObj.get());
-}
-
-// ------------------------------ BracketAccessorNode --------------------------------
-
-RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
-    RegisterID* property = generator.emitNode(m_subscript);
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
-}
-
-// ------------------------------ DotAccessorNode --------------------------------
-
-RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RegisterID* base = generator.emitNode(m_base);
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
-}
-
-// ------------------------------ ArgumentListNode -----------------------------
-
-RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    ASSERT(m_expr);
-    return generator.emitNode(dst, m_expr);
-}
-
-// ------------------------------ NewExprNode ----------------------------------
-
-RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> func = generator.emitNode(m_expr);
-    return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset());
-}
-
-// ------------------------------ EvalFunctionCallNode ----------------------------------
-
-RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> func = generator.tempDestination(dst);
-    RefPtr<RegisterID> thisRegister = generator.newTemporary();
-    generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
-    generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval);
-    return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-}
-
-// ------------------------------ FunctionCallValueNode ----------------------------------
-
-RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> func = generator.emitNode(m_expr);
-    RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
-    return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-}
-
-// ------------------------------ FunctionCallResolveNode ----------------------------------
-
-RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
-        RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
-        return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-    }
-
-    int index = 0;
-    size_t depth = 0;
-    JSObject* globalObject = 0;
-    if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
-        RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
-        RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
-        return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-    }
-
-    RefPtr<RegisterID> func = generator.newTemporary();
-    RefPtr<RegisterID> thisRegister = generator.newTemporary();
-    int identifierStart = divot() - startOffset();
-    generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
-    generator.emitResolveWithBase(thisRegister.get(), func.get(), m_ident);
-    return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-}
-
-// ------------------------------ FunctionCallBracketNode ----------------------------------
-
-RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> base = generator.emitNode(m_base);
-    RegisterID* property = generator.emitNode(m_subscript);
-    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
-    RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
-    RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
-    return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-}
-
-// ------------------------------ FunctionCallDotNode ----------------------------------
-
-RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> function = generator.tempDestination(dst);
-    RefPtr<RegisterID> thisRegister = generator.newTemporary();
-    generator.emitNode(thisRegister.get(), m_base);
-    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
-    generator.emitMethodCheck();
-    generator.emitGetById(function.get(), thisRegister.get(), m_ident);
-    return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-}
-
-RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<Label> realCall = generator.newLabel();
-    RefPtr<Label> end = generator.newLabel();
-    RefPtr<RegisterID> base = generator.emitNode(m_base);
-    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
-    RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
-    RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
-    generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
-    {
-        RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
-        RefPtr<RegisterID> thisRegister = generator.newTemporary();
-        ArgumentListNode* oldList = m_args->m_listNode;
-        if (m_args->m_listNode && m_args->m_listNode->m_expr) {
-            generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
-            m_args->m_listNode = m_args->m_listNode->m_next;
-        } else
-            generator.emitLoad(thisRegister.get(), jsNull());
-
-        generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-        generator.emitJump(end.get());
-        m_args->m_listNode = oldList;
-    }
-    generator.emitLabel(realCall.get());
-    {
-        RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
-        generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-    }
-    generator.emitLabel(end.get());
-    return finalDestination.get();
-}
-    
-static bool areTrivialApplyArguments(ArgumentsNode* args)
-{
-    return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
-        || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
-}
-
-RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    // A few simple cases can be trivially handled as ordinary function calls.
-    // function.apply(), function.apply(arg) -> identical to function.call
-    // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
-    bool mayBeCall = areTrivialApplyArguments(m_args);
-
-    RefPtr<Label> realCall = generator.newLabel();
-    RefPtr<Label> end = generator.newLabel();
-    RefPtr<RegisterID> base = generator.emitNode(m_base);
-    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
-    RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
-    RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
-    generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
-    {
-        if (mayBeCall) {
-            RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
-            RefPtr<RegisterID> thisRegister = generator.newTemporary();
-            ArgumentListNode* oldList = m_args->m_listNode;
-            if (m_args->m_listNode && m_args->m_listNode->m_expr) {
-                generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
-                m_args->m_listNode = m_args->m_listNode->m_next;
-                if (m_args->m_listNode) {
-                    ASSERT(m_args->m_listNode->m_expr->isSimpleArray());
-                    ASSERT(!m_args->m_listNode->m_next);
-                    m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData());
-                }
-            } else
-                generator.emitLoad(thisRegister.get(), jsNull());
-            generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-            m_args->m_listNode = oldList;
-        } else {
-            ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
-            RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
-            RefPtr<RegisterID> argsCountRegister = generator.newTemporary();
-            RefPtr<RegisterID> thisRegister = generator.newTemporary();
-            RefPtr<RegisterID> argsRegister = generator.newTemporary();
-            generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
-            ArgumentListNode* args = m_args->m_listNode->m_next;
-            bool isArgumentsApply = false;
-            if (args->m_expr->isResolveNode()) {
-                ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr);
-                isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier());
-                if (isArgumentsApply)
-                    generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments());
-            }
-            if (!isArgumentsApply)
-                generator.emitNode(argsRegister.get(), args->m_expr);
-            while ((args = args->m_next))
-                generator.emitNode(args->m_expr);
-
-            generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get());
-            generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
-        }
-        generator.emitJump(end.get());
-    }
-    generator.emitLabel(realCall.get());
-    {
-        RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
-        generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-    }
-    generator.emitLabel(end.get());
-    return finalDestination.get();
-}
-
-// ------------------------------ PostfixResolveNode ----------------------------------
-
-static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
-{
-    return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
-}
-
-static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
-{
-    if (srcDst == dst)
-        return generator.emitToJSNumber(dst, srcDst);
-    return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
-}
-
-RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (RegisterID* local = generator.registerFor(m_ident)) {
-        if (generator.isLocalConstant(m_ident)) {
-            if (dst == generator.ignoredResult())
-                return 0;
-            return generator.emitToJSNumber(generator.finalDestination(dst), local);
-        }
-
-        if (dst == generator.ignoredResult())
-            return emitPreIncOrDec(generator, local, m_operator);
-        return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
-    }
-
-    int index = 0;
-    size_t depth = 0;
-    JSObject* globalObject = 0;
-    if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
-        RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
-        RegisterID* oldValue;
-        if (dst == generator.ignoredResult()) {
-            oldValue = 0;
-            emitPreIncOrDec(generator, value.get(), m_operator);
-        } else {
-            oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
-        }
-        generator.emitPutScopedVar(depth, index, value.get(), globalObject);
-        return oldValue;
-    }
-
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    RefPtr<RegisterID> value = generator.newTemporary();
-    RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
-    RegisterID* oldValue;
-    if (dst == generator.ignoredResult()) {
-        oldValue = 0;
-        emitPreIncOrDec(generator, value.get(), m_operator);
-    } else {
-        oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
-    }
-    generator.emitPutById(base.get(), m_ident, value.get());
-    return oldValue;
-}
-
-// ------------------------------ PostfixBracketNode ----------------------------------
-
-RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> base = generator.emitNode(m_base);
-    RefPtr<RegisterID> property = generator.emitNode(m_subscript);
-
-    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
-    RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
-    RegisterID* oldValue;
-    if (dst == generator.ignoredResult()) {
-        oldValue = 0;
-        if (m_operator == OpPlusPlus)
-            generator.emitPreInc(value.get());
-        else
-            generator.emitPreDec(value.get());
-    } else {
-        oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
-    }
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitPutByVal(base.get(), property.get(), value.get());
-    return oldValue;
-}
-
-// ------------------------------ PostfixDotNode ----------------------------------
-
-RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> base = generator.emitNode(m_base);
-
-    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
-    RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
-    RegisterID* oldValue;
-    if (dst == generator.ignoredResult()) {
-        oldValue = 0;
-        if (m_operator == OpPlusPlus)
-            generator.emitPreInc(value.get());
-        else
-            generator.emitPreDec(value.get());
-    } else {
-        oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
-    }
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitPutById(base.get(), m_ident, value.get());
-    return oldValue;
-}
-
-// ------------------------------ PostfixErrorNode -----------------------------------
-
-RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
-    return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference.");
-}
-
-// ------------------------------ DeleteResolveNode -----------------------------------
-
-RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (generator.registerFor(m_ident))
-        return generator.emitLoad(generator.finalDestination(dst), false);
-
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
-    return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
-}
-
-// ------------------------------ DeleteBracketNode -----------------------------------
-
-RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> r0 = generator.emitNode(m_base);
-    RegisterID* r1 = generator.emitNode(m_subscript);
-
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
-}
-
-// ------------------------------ DeleteDotNode -----------------------------------
-
-RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RegisterID* r0 = generator.emitNode(m_base);
-
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
-}
-
-// ------------------------------ DeleteValueNode -----------------------------------
-
-RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    generator.emitNode(generator.ignoredResult(), m_expr);
-
-    // delete on a non-location expression ignores the value and returns true
-    return generator.emitLoad(generator.finalDestination(dst), true);
-}
-
-// ------------------------------ VoidNode -------------------------------------
-
-RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (dst == generator.ignoredResult()) {
-        generator.emitNode(generator.ignoredResult(), m_expr);
-        return 0;
-    }
-    RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
-    return generator.emitLoad(dst, jsUndefined());
-}
-
-// ------------------------------ TypeOfValueNode -----------------------------------
-
-RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (RegisterID* local = generator.registerFor(m_ident)) {
-        if (dst == generator.ignoredResult())
-            return 0;
-        return generator.emitTypeOf(generator.finalDestination(dst), local);
-    }
-
-    RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
-    generator.emitGetById(scratch.get(), scratch.get(), m_ident);
-    if (dst == generator.ignoredResult())
-        return 0;
-    return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
-}
-
-// ------------------------------ TypeOfValueNode -----------------------------------
-
-RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (dst == generator.ignoredResult()) {
-        generator.emitNode(generator.ignoredResult(), m_expr);
-        return 0;
-    }
-    RefPtr<RegisterID> src = generator.emitNode(m_expr);
-    return generator.emitTypeOf(generator.finalDestination(dst), src.get());
-}
-
-// ------------------------------ PrefixResolveNode ----------------------------------
-
-RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (RegisterID* local = generator.registerFor(m_ident)) {
-        if (generator.isLocalConstant(m_ident)) {
-            if (dst == generator.ignoredResult())
-                return 0;
-            RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
-            return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
-        }
-
-        emitPreIncOrDec(generator, local, m_operator);
-        return generator.moveToDestinationIfNeeded(dst, local);
-    }
-
-    int index = 0;
-    size_t depth = 0;
-    JSObject* globalObject = 0;
-    if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
-        RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
-        emitPreIncOrDec(generator, propDst.get(), m_operator);
-        generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
-        return generator.moveToDestinationIfNeeded(dst, propDst.get());
-    }
-
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    RefPtr<RegisterID> propDst = generator.tempDestination(dst);
-    RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
-    emitPreIncOrDec(generator, propDst.get(), m_operator);
-    generator.emitPutById(base.get(), m_ident, propDst.get());
-    return generator.moveToDestinationIfNeeded(dst, propDst.get());
-}
-
-// ------------------------------ PrefixBracketNode ----------------------------------
-
-RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> base = generator.emitNode(m_base);
-    RefPtr<RegisterID> property = generator.emitNode(m_subscript);
-    RefPtr<RegisterID> propDst = generator.tempDestination(dst);
-
-    generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
-    RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
-    if (m_operator == OpPlusPlus)
-        generator.emitPreInc(value);
-    else
-        generator.emitPreDec(value);
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitPutByVal(base.get(), property.get(), value);
-    return generator.moveToDestinationIfNeeded(dst, propDst.get());
-}
-
-// ------------------------------ PrefixDotNode ----------------------------------
-
-RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> base = generator.emitNode(m_base);
-    RefPtr<RegisterID> propDst = generator.tempDestination(dst);
-
-    generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
-    RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
-    if (m_operator == OpPlusPlus)
-        generator.emitPreInc(value);
-    else
-        generator.emitPreDec(value);
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitPutById(base.get(), m_ident, value);
-    return generator.moveToDestinationIfNeeded(dst, propDst.get());
-}
-
-// ------------------------------ PrefixErrorNode -----------------------------------
-
-RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
-    return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference.");
-}
-
-// ------------------------------ Unary Operation Nodes -----------------------------------
-
-RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RegisterID* src = generator.emitNode(m_expr);
-    return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
-}
-
-// ------------------------------ Binary Operation Nodes -----------------------------------
-
-// BinaryOpNode::emitStrcat:
-//
-// This node generates an op_strcat operation.  This opcode can handle concatenation of three or
-// more values, where we can determine a set of separate op_add operations would be operating on
-// string values.
-//
-// This function expects to be operating on a graph of AST nodes looking something like this:
-//
-//     (a)...     (b)
-//          \   /
-//           (+)     (c)
-//              \   /
-//      [d]     ((+))
-//         \    /
-//          [+=]
-//
-// The assignment operation is optional, if it exists the register holding the value on the
-// lefthand side of the assignment should be passing as the optional 'lhs' argument.
-//
-// The method should be called on the node at the root of the tree of regular binary add
-// operations (marked in the diagram with a double set of parentheses).  This node must
-// be performing a string concatenation (determined by statically detecting that at least
-// one child must be a string).  
-//
-// Since the minimum number of values being concatenated together is expected to be 3, if
-// a lhs to a concatenating assignment is not provided then the  root add should have at
-// least one left child that is also an add that can be determined to be operating on strings.
-//
-RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
-{
-    ASSERT(isAdd());
-    ASSERT(resultDescriptor().definitelyIsString());
-
-    // Create a list of expressions for all the adds in the tree of nodes we can convert into
-    // a string concatenation.  The rightmost node (c) is added first.  The rightmost node is
-    // added first, and the leftmost child is never added, so the vector produced for the
-    // example above will be [ c, b ].
-    Vector<ExpressionNode*, 16> reverseExpressionList;
-    reverseExpressionList.append(m_expr2);
-
-    // Examine the left child of the add.  So long as this is a string add, add its right-child
-    // to the list, and keep processing along the left fork.
-    ExpressionNode* leftMostAddChild = m_expr1;
-    while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
-        reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
-        leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
-    }
-
-    Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
-
-    // If there is an assignment, allocate a temporary to hold the lhs after conversion.
-    // We could possibly avoid this (the lhs is converted last anyway, we could let the
-    // op_strcat node handle its conversion if required).
-    if (lhs)
-        temporaryRegisters.append(generator.newTemporary());
-
-    // Emit code for the leftmost node ((a) in the example).
-    temporaryRegisters.append(generator.newTemporary());
-    RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
-    generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
-
-    // Note on ordering of conversions:
-    //
-    // We maintain the same ordering of conversions as we would see if the concatenations
-    // was performed as a sequence of adds (otherwise this optimization could change
-    // behaviour should an object have been provided a valueOf or toString method).
-    //
-    // Considering the above example, the sequnce of execution is:
-    //     * evaluate operand (a)
-    //     * evaluate operand (b)
-    //     * convert (a) to primitive   <-  (this would be triggered by the first add)
-    //     * convert (b) to primitive   <-  (ditto)
-    //     * evaluate operand (c)
-    //     * convert (c) to primitive   <-  (this would be triggered by the second add)
-    // And optionally, if there is an assignment:
-    //     * convert (d) to primitive   <-  (this would be triggered by the assigning addition)
-    //
-    // As such we do not plant an op to convert the leftmost child now.  Instead, use
-    // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
-    // once the second node has been generated.  However, if the leftmost child is an
-    // immediate we can trivially determine that no conversion will be required.
-    // If this is the case
-    if (leftMostAddChild->isString())
-        leftMostAddChildTempRegister = 0;
-
-    while (reverseExpressionList.size()) {
-        ExpressionNode* node = reverseExpressionList.last();
-        reverseExpressionList.removeLast();
-
-        // Emit the code for the current node.
-        temporaryRegisters.append(generator.newTemporary());
-        generator.emitNode(temporaryRegisters.last().get(), node);
-
-        // On the first iteration of this loop, when we first reach this point we have just
-        // generated the second node, which means it is time to convert the leftmost operand.
-        if (leftMostAddChildTempRegister) {
-            generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
-            leftMostAddChildTempRegister = 0; // Only do this once.
-        }
-        // Plant a conversion for this node, if necessary.
-        if (!node->isString())
-            generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
-    }
-    ASSERT(temporaryRegisters.size() >= 3);
-
-    // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
-    // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
-    if (emitExpressionInfoForMe)
-        generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
-
-    // If there is an assignment convert the lhs now.  This will also copy lhs to
-    // the temporary register we allocated for it.
-    if (lhs)
-        generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
-
-    return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
-}
-
-RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    OpcodeID opcodeID = this->opcodeID();
-
-    if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString())
-        return emitStrcat(generator, dst);
-
-    if (opcodeID == op_neq) {
-        if (m_expr1->isNull() || m_expr2->isNull()) {
-            RefPtr<RegisterID> src = generator.tempDestination(dst);
-            generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
-            return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
-        }
-    }
-
-    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
-    RegisterID* src2 = generator.emitNode(m_expr2);
-    return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
-}
-
-RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (m_expr1->isNull() || m_expr2->isNull()) {
-        RefPtr<RegisterID> src = generator.tempDestination(dst);
-        generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
-        return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
-    }
-
-    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
-    RegisterID* src2 = generator.emitNode(m_expr2);
-    return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
-    RegisterID* src2 = generator.emitNode(m_expr2);
-    return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
-}
-
-RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
-    RegisterID* src2 = generator.emitNode(m_expr2);
-    return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
-}
-
-RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
-    RegisterID* src2 = generator.emitNode(m_expr2);
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
-}
-
-RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
-    RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
-
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitGetByIdExceptionInfo(op_instanceof);
-    RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
-
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
-}
-
-// ------------------------------ LogicalOpNode ----------------------------
-
-RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> temp = generator.tempDestination(dst);
-    RefPtr<Label> target = generator.newLabel();
-    
-    generator.emitNode(temp.get(), m_expr1);
-    if (m_operator == OpLogicalAnd)
-        generator.emitJumpIfFalse(temp.get(), target.get());
-    else
-        generator.emitJumpIfTrue(temp.get(), target.get());
-    generator.emitNode(temp.get(), m_expr2);
-    generator.emitLabel(target.get());
-
-    return generator.moveToDestinationIfNeeded(dst, temp.get());
-}
-
-// ------------------------------ ConditionalNode ------------------------------
-
-RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> newDst = generator.finalDestination(dst);
-    RefPtr<Label> beforeElse = generator.newLabel();
-    RefPtr<Label> afterElse = generator.newLabel();
-
-    RegisterID* cond = generator.emitNode(m_logical);
-    generator.emitJumpIfFalse(cond, beforeElse.get());
-
-    generator.emitNode(newDst.get(), m_expr1);
-    generator.emitJump(afterElse.get());
-
-    generator.emitLabel(beforeElse.get());
-    generator.emitNode(newDst.get(), m_expr2);
-
-    generator.emitLabel(afterElse.get());
-
-    return newDst.get();
-}
-
-// ------------------------------ ReadModifyResolveNode -----------------------------------
-
-// FIXME: should this be moved to be a method on BytecodeGenerator?
-static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
-{
-    OpcodeID opcodeID;
-    switch (oper) {
-        case OpMultEq:
-            opcodeID = op_mul;
-            break;
-        case OpDivEq:
-            opcodeID = op_div;
-            break;
-        case OpPlusEq:
-            if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
-                return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
-            opcodeID = op_add;
-            break;
-        case OpMinusEq:
-            opcodeID = op_sub;
-            break;
-        case OpLShift:
-            opcodeID = op_lshift;
-            break;
-        case OpRShift:
-            opcodeID = op_rshift;
-            break;
-        case OpURShift:
-            opcodeID = op_urshift;
-            break;
-        case OpAndEq:
-            opcodeID = op_bitand;
-            break;
-        case OpXOrEq:
-            opcodeID = op_bitxor;
-            break;
-        case OpOrEq:
-            opcodeID = op_bitor;
-            break;
-        case OpModEq:
-            opcodeID = op_mod;
-            break;
-        default:
-            ASSERT_NOT_REACHED();
-            return dst;
-    }
-
-    RegisterID* src2 = generator.emitNode(m_right);
-
-    // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
-    // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
-    if (emitExpressionInfoForMe)
-        generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
-
-    return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
-}
-
-RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (RegisterID* local = generator.registerFor(m_ident)) {
-        if (generator.isLocalConstant(m_ident)) {
-            return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
-        }
-        
-        if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
-            RefPtr<RegisterID> result = generator.newTemporary();
-            generator.emitMove(result.get(), local);
-            emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
-            generator.emitMove(local, result.get());
-            return generator.moveToDestinationIfNeeded(dst, result.get());
-        }
-        
-        RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
-        return generator.moveToDestinationIfNeeded(dst, result);
-    }
-
-    int index = 0;
-    size_t depth = 0;
-    JSObject* globalObject = 0;
-    if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
-        RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
-        RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
-        generator.emitPutScopedVar(depth, index, result, globalObject);
-        return result;
-    }
-
-    RefPtr<RegisterID> src1 = generator.tempDestination(dst);
-    generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
-    RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
-    RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
-    return generator.emitPutById(base.get(), m_ident, result);
-}
-
-// ------------------------------ AssignResolveNode -----------------------------------
-
-RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (RegisterID* local = generator.registerFor(m_ident)) {
-        if (generator.isLocalConstant(m_ident))
-            return generator.emitNode(dst, m_right);
-        
-        RegisterID* result = generator.emitNode(local, m_right);
-        return generator.moveToDestinationIfNeeded(dst, result);
-    }
-
-    int index = 0;
-    size_t depth = 0;
-    JSObject* globalObject = 0;
-    if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
-        if (dst == generator.ignoredResult())
-            dst = 0;
-        RegisterID* value = generator.emitNode(dst, m_right);
-        generator.emitPutScopedVar(depth, index, value, globalObject);
-        return value;
-    }
-
-    RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
-    if (dst == generator.ignoredResult())
-        dst = 0;
-    RegisterID* value = generator.emitNode(dst, m_right);
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    return generator.emitPutById(base.get(), m_ident, value);
-}
-
-// ------------------------------ AssignDotNode -----------------------------------
-
-RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
-    RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
-    RegisterID* result = generator.emitNode(value.get(), m_right);
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitPutById(base.get(), m_ident, result);
-    return generator.moveToDestinationIfNeeded(dst, result);
-}
-
-// ------------------------------ ReadModifyDotNode -----------------------------------
-
-RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
-
-    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
-    RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
-    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
-
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    return generator.emitPutById(base.get(), m_ident, updatedValue);
-}
-
-// ------------------------------ AssignErrorNode -----------------------------------
-
-RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
-    return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
-}
-
-// ------------------------------ AssignBracketNode -----------------------------------
-
-RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
-    RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
-    RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
-    RegisterID* result = generator.emitNode(value.get(), m_right);
-
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitPutByVal(base.get(), property.get(), result);
-    return generator.moveToDestinationIfNeeded(dst, result);
-}
-
-// ------------------------------ ReadModifyBracketNode -----------------------------------
-
-RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
-    RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
-
-    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
-    RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
-    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
-
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitPutByVal(base.get(), property.get(), updatedValue);
-
-    return updatedValue;
-}
-
-// ------------------------------ CommaNode ------------------------------------
-
-RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    ASSERT(m_expressions.size() > 1);
-    for (size_t i = 0; i < m_expressions.size() - 1; i++)
-        generator.emitNode(generator.ignoredResult(), m_expressions[i]);
-    return generator.emitNode(dst, m_expressions.last());
-}
-
-// ------------------------------ ConstDeclNode ------------------------------------
-
-RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
-{
-    if (RegisterID* local = generator.constRegisterFor(m_ident)) {
-        if (!m_init)
-            return local;
-
-        return generator.emitNode(local, m_init);
-    }
-    
-    // FIXME: While this code should only be hit in eval code, it will potentially
-    // assign to the wrong base if m_ident exists in an intervening dynamic scope.
-    RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
-    RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
-    return generator.emitPutById(base.get(), m_ident, value);
-}
-
-RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
-    RegisterID* result = 0;
-    for (ConstDeclNode* n = this; n; n = n->m_next)
-        result = n->emitCodeSingle(generator);
-
-    return result;
-}
-
-// ------------------------------ ConstStatementNode -----------------------------
-
-RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    return generator.emitNode(m_next);
-}
-
-// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
-
-static inline void statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst)
-{
-    size_t size = statements.size();
-    for (size_t i = 0; i < size; ++i)
-        generator.emitNode(dst, statements[i]);
-}
-
-// ------------------------------ BlockNode ------------------------------------
-
-RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    statementListEmitCode(m_children, generator, dst);
-    return 0;
-}
-
-// ------------------------------ EmptyStatementNode ---------------------------
-
-RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    return dst;
-}
-
-// ------------------------------ DebuggerStatementNode ---------------------------
-
-RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
-    return dst;
-}
-
-// ------------------------------ ExprStatementNode ----------------------------
-
-RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    ASSERT(m_expr);
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); 
-    return generator.emitNode(dst, m_expr);
-}
-
-// ------------------------------ VarStatementNode ----------------------------
-
-RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
-    ASSERT(m_expr);
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    return generator.emitNode(m_expr);
-}
-
-// ------------------------------ IfNode ---------------------------------------
-
-RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    
-    RefPtr<Label> afterThen = generator.newLabel();
-
-    RegisterID* cond = generator.emitNode(m_condition);
-    generator.emitJumpIfFalse(cond, afterThen.get());
-
-    generator.emitNode(dst, m_ifBlock);
-    generator.emitLabel(afterThen.get());
-
-    // FIXME: This should return the last statement executed so that it can be returned as a Completion.
-    return 0;
-}
-
-// ------------------------------ IfElseNode ---------------------------------------
-
-RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    
-    RefPtr<Label> beforeElse = generator.newLabel();
-    RefPtr<Label> afterElse = generator.newLabel();
-
-    RegisterID* cond = generator.emitNode(m_condition);
-    generator.emitJumpIfFalse(cond, beforeElse.get());
-
-    generator.emitNode(dst, m_ifBlock);
-    generator.emitJump(afterElse.get());
-
-    generator.emitLabel(beforeElse.get());
-
-    generator.emitNode(dst, m_elseBlock);
-
-    generator.emitLabel(afterElse.get());
-
-    // FIXME: This should return the last statement executed so that it can be returned as a Completion.
-    return 0;
-}
-
-// ------------------------------ DoWhileNode ----------------------------------
-
-RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-
-    RefPtr<Label> topOfLoop = generator.newLabel();
-    generator.emitLabel(topOfLoop.get());
-
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-   
-    RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
-
-    generator.emitLabel(scope->continueTarget());
-    generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
-    RegisterID* cond = generator.emitNode(m_expr);
-    generator.emitJumpIfTrue(cond, topOfLoop.get());
-
-    generator.emitLabel(scope->breakTarget());
-    return result.get();
-}
-
-// ------------------------------ WhileNode ------------------------------------
-
-RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-
-    generator.emitJump(scope->continueTarget());
-
-    RefPtr<Label> topOfLoop = generator.newLabel();
-    generator.emitLabel(topOfLoop.get());
-    
-    generator.emitNode(dst, m_statement);
-
-    generator.emitLabel(scope->continueTarget());
-    generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
-    RegisterID* cond = generator.emitNode(m_expr);
-    generator.emitJumpIfTrue(cond, topOfLoop.get());
-
-    generator.emitLabel(scope->breakTarget());
-    
-    // FIXME: This should return the last statement executed so that it can be returned as a Completion
-    return 0;
-}
-
-// ------------------------------ ForNode --------------------------------------
-
-RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-
-    if (m_expr1)
-        generator.emitNode(generator.ignoredResult(), m_expr1);
-
-    RefPtr<Label> condition = generator.newLabel();
-    generator.emitJump(condition.get());
-
-    RefPtr<Label> topOfLoop = generator.newLabel();
-    generator.emitLabel(topOfLoop.get());
-
-    RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
-
-    generator.emitLabel(scope->continueTarget());
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    if (m_expr3)
-        generator.emitNode(generator.ignoredResult(), m_expr3);
-
-    generator.emitLabel(condition.get());
-    if (m_expr2) {
-        RegisterID* cond = generator.emitNode(m_expr2);
-        generator.emitJumpIfTrue(cond, topOfLoop.get());
-    } else
-        generator.emitJump(topOfLoop.get());
-
-    generator.emitLabel(scope->breakTarget());
-    return result.get();
-}
-
-// ------------------------------ ForInNode ------------------------------------
-
-RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
-
-    if (!m_lexpr->isLocation())
-        return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
-
-    RefPtr<Label> continueTarget = generator.newLabel(); 
-
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-
-    if (m_init)
-        generator.emitNode(generator.ignoredResult(), m_init);
-    RegisterID* forInBase = generator.emitNode(m_expr);
-    RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
-    generator.emitJump(scope->continueTarget());
-
-    RefPtr<Label> loopStart = generator.newLabel();
-    generator.emitLabel(loopStart.get());
-
-    RegisterID* propertyName;
-    if (m_lexpr->isResolveNode()) {
-        const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
-        propertyName = generator.registerFor(ident);
-        if (!propertyName) {
-            propertyName = generator.newTemporary();
-            RefPtr<RegisterID> protect = propertyName;
-            RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
-
-            generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-            generator.emitPutById(base, ident, propertyName);
-        }
-    } else if (m_lexpr->isDotAccessorNode()) {
-        DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
-        const Identifier& ident = assignNode->identifier();
-        propertyName = generator.newTemporary();
-        RefPtr<RegisterID> protect = propertyName;
-        RegisterID* base = generator.emitNode(assignNode->base());
-
-        generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
-        generator.emitPutById(base, ident, propertyName);
-    } else {
-        ASSERT(m_lexpr->isBracketAccessorNode());
-        BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
-        propertyName = generator.newTemporary();
-        RefPtr<RegisterID> protect = propertyName;
-        RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
-        RegisterID* subscript = generator.emitNode(assignNode->subscript());
-        
-        generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
-        generator.emitPutByVal(base.get(), subscript, propertyName);
-    }   
-
-    generator.emitNode(dst, m_statement);
-
-    generator.emitLabel(scope->continueTarget());
-    generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    generator.emitLabel(scope->breakTarget());
-    return dst;
-}
-
-// ------------------------------ ContinueNode ---------------------------------
-
-// ECMA 12.7
-RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    
-    LabelScope* scope = generator.continueTarget(m_ident);
-
-    if (!scope)
-        return m_ident.isEmpty()
-            ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
-            : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
-
-    generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
-    return dst;
-}
-
-// ------------------------------ BreakNode ------------------------------------
-
-// ECMA 12.8
-RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    
-    LabelScope* scope = generator.breakTarget(m_ident);
-    
-    if (!scope)
-        return m_ident.isEmpty()
-            ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
-            : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
-
-    generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
-    return dst;
-}
-
-// ------------------------------ ReturnNode -----------------------------------
-
-RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    if (generator.codeType() != FunctionCode)
-        return emitThrowError(generator, SyntaxError, "Invalid return statement.");
-
-    if (dst == generator.ignoredResult())
-        dst = 0;
-    RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
-    RefPtr<RegisterID> returnRegister;
-    if (generator.scopeDepth()) {
-        RefPtr<Label> l0 = generator.newLabel();
-        if (generator.hasFinaliser() && !r0->isTemporary()) {
-            returnRegister = generator.emitMove(generator.newTemporary(), r0);
-            r0 = returnRegister.get();
-        }
-        generator.emitJumpScopes(l0.get(), 0);
-        generator.emitLabel(l0.get());
-    }
-    generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
-    return generator.emitReturn(r0);
-}
-
-// ------------------------------ WithNode -------------------------------------
-
-RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    
-    RefPtr<RegisterID> scope = generator.newTemporary();
-    generator.emitNode(scope.get(), m_expr); // scope must be protected until popped
-    generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
-    generator.emitPushScope(scope.get());
-    RegisterID* result = generator.emitNode(dst, m_statement);
-    generator.emitPopScope();
-    return result;
-}
-
-// ------------------------------ CaseBlockNode --------------------------------
-
-enum SwitchKind { 
-    SwitchUnset = 0,
-    SwitchNumber = 1, 
-    SwitchString = 2, 
-    SwitchNeither = 3 
-};
-
-static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
-{
-    for (; list; list = list->getNext()) {
-        ExpressionNode* clauseExpression = list->getClause()->expr();
-        literalVector.append(clauseExpression);
-        if (clauseExpression->isNumber()) {
-            double value = static_cast<NumberNode*>(clauseExpression)->value();
-            int32_t intVal = static_cast<int32_t>(value);
-            if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
-                typeForTable = SwitchNeither;
-                break;
-            }
-            if (intVal < min_num)
-                min_num = intVal;
-            if (intVal > max_num)
-                max_num = intVal;
-            typeForTable = SwitchNumber;
-            continue;
-        }
-        if (clauseExpression->isString()) {
-            if (typeForTable & ~SwitchString) {
-                typeForTable = SwitchNeither;
-                break;
-            }
-            const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
-            if (singleCharacterSwitch &= value.size() == 1) {
-                int32_t intVal = value.rep()->data()[0];
-                if (intVal < min_num)
-                    min_num = intVal;
-                if (intVal > max_num)
-                    max_num = intVal;
-            }
-            typeForTable = SwitchString;
-            continue;
-        }
-        typeForTable = SwitchNeither;
-        break;        
-    }
-}
-    
-SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
-{
-    SwitchKind typeForTable = SwitchUnset;
-    bool singleCharacterSwitch = true;
-    
-    processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
-    processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
-    
-    if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
-        return SwitchInfo::SwitchNone;
-    
-    if (typeForTable == SwitchNumber) {
-        int32_t range = max_num - min_num;
-        if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
-            return SwitchInfo::SwitchImmediate;
-        return SwitchInfo::SwitchNone;
-    } 
-    
-    ASSERT(typeForTable == SwitchString);
-    
-    if (singleCharacterSwitch) {
-        int32_t range = max_num - min_num;
-        if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
-            return SwitchInfo::SwitchCharacter;
-    }
-
-    return SwitchInfo::SwitchString;
-}
-
-RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
-{
-    RefPtr<Label> defaultLabel;
-    Vector<RefPtr<Label>, 8> labelVector;
-    Vector<ExpressionNode*, 8> literalVector;
-    int32_t min_num = std::numeric_limits<int32_t>::max();
-    int32_t max_num = std::numeric_limits<int32_t>::min();
-    SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
-
-    if (switchType != SwitchInfo::SwitchNone) {
-        // Prepare the various labels
-        for (uint32_t i = 0; i < literalVector.size(); i++)
-            labelVector.append(generator.newLabel());
-        defaultLabel = generator.newLabel();
-        generator.beginSwitch(switchExpression, switchType);
-    } else {
-        // Setup jumps
-        for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
-            RefPtr<RegisterID> clauseVal = generator.newTemporary();
-            generator.emitNode(clauseVal.get(), list->getClause()->expr());
-            generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
-            labelVector.append(generator.newLabel());
-            generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
-        }
-        
-        for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
-            RefPtr<RegisterID> clauseVal = generator.newTemporary();
-            generator.emitNode(clauseVal.get(), list->getClause()->expr());
-            generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
-            labelVector.append(generator.newLabel());
-            generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
-        }
-        defaultLabel = generator.newLabel();
-        generator.emitJump(defaultLabel.get());
-    }
-
-    RegisterID* result = 0;
-
-    size_t i = 0;
-    for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
-        generator.emitLabel(labelVector[i++].get());
-        statementListEmitCode(list->getClause()->children(), generator, dst);
-    }
-
-    if (m_defaultClause) {
-        generator.emitLabel(defaultLabel.get());
-        statementListEmitCode(m_defaultClause->children(), generator, dst);
-    }
-
-    for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
-        generator.emitLabel(labelVector[i++].get());
-        statementListEmitCode(list->getClause()->children(), generator, dst);
-    }
-    if (!m_defaultClause)
-        generator.emitLabel(defaultLabel.get());
-
-    ASSERT(i == labelVector.size());
-    if (switchType != SwitchInfo::SwitchNone) {
-        ASSERT(labelVector.size() == literalVector.size());
-        generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
-    }
-    return result;
-}
-
-// ------------------------------ SwitchNode -----------------------------------
-
-RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    
-    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
-
-    RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
-    RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
-
-    generator.emitLabel(scope->breakTarget());
-    return r1;
-}
-
-// ------------------------------ LabelNode ------------------------------------
+// ------------------------------ StatementNode --------------------------------
 
 
-RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void StatementNode::setLoc(int firstLine, int lastLine)
 {
 {
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-
-    if (generator.breakTarget(m_name))
-        return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
-
-    RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
-    RegisterID* r0 = generator.emitNode(dst, m_statement);
-
-    generator.emitLabel(scope->breakTarget());
-    return r0;
+    m_line = firstLine;
+    m_lastLine = lastLine;
 }
 
 }
 
-// ------------------------------ ThrowNode ------------------------------------
+// ------------------------------ SourceElements --------------------------------
 
 
-RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void SourceElements::append(StatementNode* statement)
 {
 {
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-
-    if (dst == generator.ignoredResult())
-        dst = 0;
-    RefPtr<RegisterID> expr = generator.emitNode(m_expr);
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitThrow(expr.get());
-    return 0;
+    if (statement->isEmptyStatement())
+        return;
+    m_statements.append(statement);
 }
 
 }
 
-// ------------------------------ TryNode --------------------------------------
-
-RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+inline StatementNode* SourceElements::singleStatement() const
 {
 {
-    // NOTE: The catch and finally blocks must be labeled explicitly, so the
-    // optimizer knows they may be jumped to from anywhere.
-
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-
-    RefPtr<Label> tryStartLabel = generator.newLabel();
-    RefPtr<Label> finallyStart;
-    RefPtr<RegisterID> finallyReturnAddr;
-    if (m_finallyBlock) {
-        finallyStart = generator.newLabel();
-        finallyReturnAddr = generator.newTemporary();
-        generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
-    }
-
-    generator.emitLabel(tryStartLabel.get());
-    generator.emitNode(dst, m_tryBlock);
-
-    if (m_catchBlock) {
-        RefPtr<Label> catchEndLabel = generator.newLabel();
-        
-        // Normal path: jump over the catch block.
-        generator.emitJump(catchEndLabel.get());
-
-        // Uncaught exception path: the catch block.
-        RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
-        RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
-        if (m_catchHasEval) {
-            RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
-            generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
-            generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
-            generator.emitPushScope(exceptionRegister.get());
-        } else
-            generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
-        generator.emitNode(dst, m_catchBlock);
-        generator.emitPopScope();
-        generator.emitLabel(catchEndLabel.get());
-    }
-
-    if (m_finallyBlock) {
-        generator.popFinallyContext();
-        // there may be important registers live at the time we jump
-        // to a finally block (such as for a return or throw) so we
-        // ref the highest register ever used as a conservative
-        // approach to not clobbering anything important
-        RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
-        RefPtr<Label> finallyEndLabel = generator.newLabel();
-
-        // Normal path: invoke the finally block, then jump over it.
-        generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
-        generator.emitJump(finallyEndLabel.get());
-
-        // Uncaught exception path: invoke the finally block, then re-throw the exception.
-        RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
-        RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
-        generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
-        generator.emitThrow(tempExceptionRegister.get());
-
-        // The finally block.
-        generator.emitLabel(finallyStart.get());
-        generator.emitNode(dst, m_finallyBlock);
-        generator.emitSubroutineReturn(finallyReturnAddr.get());
-
-        generator.emitLabel(finallyEndLabel.get());
-    }
-
-    return dst;
+    size_t size = m_statements.size();
+    return size == 1 ? m_statements[0] : 0;
 }
 
 // -----------------------------ScopeNodeData ---------------------------
 
 }
 
 // -----------------------------ScopeNodeData ---------------------------
 
-ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants)
+ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, int numConstants)
     : m_numConstants(numConstants)
     : m_numConstants(numConstants)
+    , m_statements(statements)
 {
     m_arena.swap(arena);
     if (varStack)
         m_varStack.swap(*varStack);
     if (funcStack)
         m_functionStack.swap(*funcStack);
 {
     m_arena.swap(arena);
     if (varStack)
         m_varStack.swap(*varStack);
     if (funcStack)
         m_functionStack.swap(*funcStack);
-    if (children)
-        children->releaseContentsIntoVector(m_children);
-}
-
-void ScopeNodeData::mark()
-{
-    FunctionStack::iterator end = m_functionStack.end();
-    for (FunctionStack::iterator ptr = m_functionStack.begin(); ptr != end; ++ptr) {
-        FunctionBodyNode* body = (*ptr)->body();
-        if (!body->isGenerated())
-            continue;
-        body->generatedBytecode().mark();
-    }
 }
 
 // ------------------------------ ScopeNode -----------------------------
 }
 
 // ------------------------------ ScopeNode -----------------------------
@@ -1836,10 +93,6 @@ ScopeNode::ScopeNode(JSGlobalData* globalData)
     , ParserArenaRefCounted(globalData)
     , m_features(NoFeatures)
 {
     , ParserArenaRefCounted(globalData)
     , m_features(NoFeatures)
 {
-#if ENABLE(CODEBLOCK_SAMPLING)
-    if (SamplingTool* sampler = globalData->interpreter->sampler())
-        sampler->notifyOfScope(this);
-#endif
 }
 
 ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
 }
 
 ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
@@ -1849,10 +102,11 @@ ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceE
     , m_features(features)
     , m_source(source)
 {
     , m_features(features)
     , m_source(source)
 {
-#if ENABLE(CODEBLOCK_SAMPLING)
-    if (SamplingTool* sampler = globalData->interpreter->sampler())
-        sampler->notifyOfScope(this);
-#endif
+}
+
+StatementNode* ScopeNode::singleStatement() const
+{
+    return m_data->m_statements ? m_data->m_statements->singleStatement() : 0;
 }
 
 // ------------------------------ ProgramNode -----------------------------
 }
 
 // ------------------------------ ProgramNode -----------------------------
@@ -1873,43 +127,6 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElem
     return node.release();
 }
 
     return node.release();
 }
 
-RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
-    generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
-
-    RefPtr<RegisterID> dstRegister = generator.newTemporary();
-    generator.emitLoad(dstRegister.get(), jsUndefined());
-    statementListEmitCode(children(), generator, dstRegister.get());
-
-    generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
-    generator.emitEnd(dstRegister.get());
-    return 0;
-}
-
-void ProgramNode::generateBytecode(ScopeChainNode* scopeChainNode)
-{
-    ScopeChain scopeChain(scopeChainNode);
-    JSGlobalObject* globalObject = scopeChain.globalObject();
-    
-    m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
-    
-    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get()));
-    generator->generate();
-
-    destroyData();
-}
-
-#if ENABLE(JIT)
-void ProgramNode::generateJITCode(ScopeChainNode* scopeChainNode)
-{
-    bytecode(scopeChainNode);
-    ASSERT(m_code);
-    ASSERT(!m_jitCode);
-    JIT::compile(scopeChainNode->globalData, m_code.get());
-    ASSERT(m_jitCode);
-}
-#endif
-
 // ------------------------------ EvalNode -----------------------------
 
 inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
 // ------------------------------ EvalNode -----------------------------
 
 inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
@@ -1928,128 +145,35 @@ PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements*
     return node.release();
 }
 
     return node.release();
 }
 
-RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
-    generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
-
-    RefPtr<RegisterID> dstRegister = generator.newTemporary();
-    generator.emitLoad(dstRegister.get(), jsUndefined());
-    statementListEmitCode(children(), generator, dstRegister.get());
-
-    generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
-    generator.emitEnd(dstRegister.get());
-    return 0;
-}
-
-void EvalNode::generateBytecode(ScopeChainNode* scopeChainNode)
-{
-    ScopeChain scopeChain(scopeChainNode);
-    JSGlobalObject* globalObject = scopeChain.globalObject();
-
-    m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
-
-    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
-    generator->generate();
-
-    // Eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time,
-    // so the entire ScopeNodeData cannot be destoyed.
-    children().clear();
-}
-
-EvalCodeBlock& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
-{
-    ASSERT(!m_code);
-
-    ScopeChain scopeChain(scopeChainNode);
-    JSGlobalObject* globalObject = scopeChain.globalObject();
-
-    m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
-
-    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
-    generator->setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
-    generator->generate();
-
-    return *m_code;
-}
-
-void EvalNode::mark()
-{
-    // We don't need to mark our own CodeBlock as the JSGlobalObject takes care of that
-    data()->mark();
-}
+// ------------------------------ FunctionBodyNode -----------------------------
 
 
-#if ENABLE(JIT)
-void EvalNode::generateJITCode(ScopeChainNode* scopeChainNode)
+FunctionParameters::FunctionParameters(ParameterNode* firstParameter)
 {
 {
-    bytecode(scopeChainNode);
-    ASSERT(m_code);
-    ASSERT(!m_jitCode);
-    JIT::compile(scopeChainNode->globalData, m_code.get());
-    ASSERT(m_jitCode);
+    for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
+        append(parameter->ident());
 }
 }
-#endif
-
-// ------------------------------ FunctionBodyNode -----------------------------
 
 inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
     : ScopeNode(globalData)
 
 inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
     : ScopeNode(globalData)
-    , m_parameters(0)
-    , m_parameterCount(0)
 {
 }
 
 inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
     : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
 {
 }
 
 inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
     : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
-    , m_parameters(0)
-    , m_parameterCount(0)
-{
-}
-
-FunctionBodyNode::~FunctionBodyNode()
 {
 {
-    for (size_t i = 0; i < m_parameterCount; ++i)
-        m_parameters[i].~Identifier();
-    fastFree(m_parameters);
 }
 
 }
 
-void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
+void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident)
 {
 {
-    Vector<Identifier> parameters;
-    for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
-        parameters.append(parameter->ident());
-    size_t count = parameters.size();
-
     setSource(source);
     setSource(source);
-    finishParsing(parameters.releaseBuffer(), count);
+    finishParsing(FunctionParameters::create(firstParameter), ident);
 }
 
 }
 
-void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount)
+void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, const Identifier& ident)
 {
     ASSERT(!source().isNull());
     m_parameters = parameters;
 {
     ASSERT(!source().isNull());
     m_parameters = parameters;
-    m_parameterCount = parameterCount;
-}
-
-void FunctionBodyNode::mark()
-{
-    if (m_code)
-        m_code->mark();
-}
-
-#if ENABLE(JIT)
-PassRefPtr<FunctionBodyNode> FunctionBodyNode::createNativeThunk(JSGlobalData* globalData)
-{
-    RefPtr<FunctionBodyNode> body = new FunctionBodyNode(globalData);
-    globalData->parser->arena().reset();
-    body->m_code.set(new CodeBlock(body.get()));
-    body->m_jitCode = JITCode(JITCode::HostFunction(globalData->jitStubs.ctiNativeCallThunk()));
-    return body.release();
-}
-#endif
-
-bool FunctionBodyNode::isHostFunction() const
-{
-    return m_code && m_code->codeType() == NativeCode;
+    m_ident = ident;
 }
 
 FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
 }
 
 FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
@@ -2068,126 +192,4 @@ PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData,
     return node.release();
 }
 
     return node.release();
 }
 
-void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode)
-{
-    // This branch is only necessary since you can still create a non-stub FunctionBodyNode by
-    // calling Parser::parse<FunctionBodyNode>().   
-    if (!data())
-        scopeChainNode->globalData->parser->reparseInPlace(scopeChainNode->globalData, this);
-    ASSERT(data());
-
-    ScopeChain scopeChain(scopeChainNode);
-    JSGlobalObject* globalObject = scopeChain.globalObject();
-
-    m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
-
-    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
-    generator->generate();
-
-    destroyData();
-}
-
-#if ENABLE(JIT)
-void FunctionBodyNode::generateJITCode(ScopeChainNode* scopeChainNode)
-{
-    bytecode(scopeChainNode);
-    ASSERT(m_code);
-    ASSERT(!m_jitCode);
-    JIT::compile(scopeChainNode->globalData, m_code.get());
-    ASSERT(m_jitCode);
-}
-#endif
-
-CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
-{
-    ASSERT(!m_code);
-
-    ScopeChain scopeChain(scopeChainNode);
-    JSGlobalObject* globalObject = scopeChain.globalObject();
-
-    m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
-
-    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()));
-    generator->setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
-    generator->generate();
-
-    return *m_code;
-}
-
-RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
-{
-    generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
-    statementListEmitCode(children(), generator, generator.ignoredResult());
-    if (children().size() && children().last()->isBlock()) {
-        BlockNode* blockNode = static_cast<BlockNode*>(children().last());
-        if (blockNode->children().size() && blockNode->children().last()->isReturnNode())
-            return 0;
-    }
-
-    RegisterID* r0 = generator.emitLoad(0, jsUndefined());
-    generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
-    generator.emitReturn(r0);
-    return 0;
-}
-
-UString FunctionBodyNode::paramString() const
-{
-    UString s("");
-    for (size_t pos = 0; pos < m_parameterCount; ++pos) {
-        if (!s.isEmpty())
-            s += ", ";
-        s += parameters()[pos].ustring();
-    }
-
-    return s;
-}
-
-Identifier* FunctionBodyNode::copyParameters()
-{
-    Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier)));
-    VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters);
-    return parameters;
-}
-
-// ------------------------------ FuncDeclNode ---------------------------------
-
-JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
-{
-    return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
-}
-
-RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    if (dst == generator.ignoredResult())
-        dst = 0;
-    return dst;
-}
-
-// ------------------------------ FuncExprNode ---------------------------------
-
-RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
-}
-
-JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
-{
-    JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
-
-    /* 
-        The Identifier in a FunctionExpression can be referenced from inside
-        the FunctionExpression's FunctionBody to allow the function to call
-        itself recursively. However, unlike in a FunctionDeclaration, the
-        Identifier in a FunctionExpression cannot be referenced from and
-        does not affect the scope enclosing the FunctionExpression.
-     */
-
-    if (!m_ident.isNull()) {
-        JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
-        func->scope().push(functionScopeObject);
-    }
-
-    return func;
-}
-
 } // namespace JSC
 } // namespace JSC
index a9f88b7378352994bf6ccf3049d8a0227fb1b0ce..c216ea86327a1f098e66e0746136e859f7c4c4a3 100644 (file)
 #include "SourceCode.h"
 #include "SymbolTable.h"
 #include <wtf/MathExtras.h>
 #include "SourceCode.h"
 #include "SymbolTable.h"
 #include <wtf/MathExtras.h>
-#include <wtf/OwnPtr.h>
 
 namespace JSC {
 
     class ArgumentListNode;
 
 namespace JSC {
 
     class ArgumentListNode;
-    class CodeBlock;
     class BytecodeGenerator;
     class BytecodeGenerator;
-    class FuncDeclNode;
-    class EvalCodeBlock;
-    class JSFunction;
-    class ProgramCodeBlock;
+    class FunctionBodyNode;
+    class Label;
     class PropertyListNode;
     class ReadModifyResolveNode;
     class RegisterID;
     class ScopeChainNode;
     class PropertyListNode;
     class ReadModifyResolveNode;
     class RegisterID;
     class ScopeChainNode;
+    class ScopeNode;
 
     typedef unsigned CodeFeatures;
 
 
     typedef unsigned CodeFeatures;
 
@@ -86,8 +83,8 @@ namespace JSC {
 
     namespace DeclarationStacks {
         enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
 
     namespace DeclarationStacks {
         enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
-        typedef Vector<std::pair<Identifier, unsigned> > VarStack;
-        typedef Vector<FuncDeclNode*> FunctionStack;
+        typedef Vector<std::pair<const Identifier*, unsigned> > VarStack;
+        typedef Vector<FunctionBodyNode*> FunctionStack;
     }
 
     struct SwitchInfo {
     }
 
     struct SwitchInfo {
@@ -96,19 +93,20 @@ namespace JSC {
         SwitchType switchType;
     };
 
         SwitchType switchType;
     };
 
-    class ParserArenaDeletable {
-    protected:
-        ParserArenaDeletable() { }
+    class ParserArenaFreeable {
+    public:
+        // ParserArenaFreeable objects are are freed when the arena is deleted.
+        // Destructors are not called. Clients must not call delete on such objects.
+        void* operator new(size_t, JSGlobalData*);
+    };
 
 
+    class ParserArenaDeletable {
     public:
         virtual ~ParserArenaDeletable() { }
 
     public:
         virtual ~ParserArenaDeletable() { }
 
-        // Objects created with this version of new are deleted when the arena is deleted.
+        // ParserArenaDeletable objects are deleted when the arena is deleted.
+        // Clients must not call delete directly on such objects.
         void* operator new(size_t, JSGlobalData*);
         void* operator new(size_t, JSGlobalData*);
-
-        // Objects created with this version of new are not deleted when the arena is deleted.
-        // Other arrangements must be made.
-        void* operator new(size_t);
     };
 
     class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> {
     };
 
     class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> {
@@ -122,34 +120,14 @@ namespace JSC {
         }
     };
 
         }
     };
 
-    class Node : public ParserArenaDeletable {
+    class Node : public ParserArenaFreeable {
     protected:
         Node(JSGlobalData*);
 
     public:
     protected:
         Node(JSGlobalData*);
 
     public:
-        /*
-            Return value: The register holding the production's value.
-                     dst: An optional parameter specifying the most efficient
-                          destination at which to store the production's value.
-                          The callee must honor dst.
+        virtual ~Node() { }
 
 
-            dst provides for a crude form of copy propagation. For example,
-
-            x = 1
-
-            becomes
-            
-            load r[x], 1
-            
-            instead of 
-
-            load r0, 1
-            mov r[x], r0
-            
-            because the assignment node, "x =", passes r[x] as dst to the number
-            node, "1".
-        */
-        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) = 0;
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0;
 
         int lineNo() const { return m_line; }
 
 
         int lineNo() const { return m_line; }
 
@@ -158,9 +136,10 @@ namespace JSC {
     };
 
     class ExpressionNode : public Node {
     };
 
     class ExpressionNode : public Node {
-    public:
+    protected:
         ExpressionNode(JSGlobalData*, ResultType = ResultType::unknownType());
 
         ExpressionNode(JSGlobalData*, ResultType = ResultType::unknownType());
 
+    public:
         virtual bool isNumber() const { return false; }
         virtual bool isString() const { return false; }
         virtual bool isNull() const { return false; }
         virtual bool isNumber() const { return false; }
         virtual bool isString() const { return false; }
         virtual bool isNull() const { return false; }
@@ -173,23 +152,24 @@ namespace JSC {
         virtual bool isCommaNode() const { return false; }
         virtual bool isSimpleArray() const { return false; }
         virtual bool isAdd() const { return false; }
         virtual bool isCommaNode() const { return false; }
         virtual bool isSimpleArray() const { return false; }
         virtual bool isAdd() const { return false; }
+        virtual bool hasConditionContextCodegen() const { return false; }
+
+        virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); }
 
         virtual ExpressionNode* stripUnaryPlus() { return this; }
 
         ResultType resultDescriptor() const { return m_resultType; }
 
 
         virtual ExpressionNode* stripUnaryPlus() { return this; }
 
         ResultType resultDescriptor() const { return m_resultType; }
 
-        // This needs to be in public in order to compile using GCC 3.x 
-        typedef enum { EvalOperator, FunctionCall } CallerType;
-
     private:
         ResultType m_resultType;
     };
 
     class StatementNode : public Node {
     private:
         ResultType m_resultType;
     };
 
     class StatementNode : public Node {
-    public:
+    protected:
         StatementNode(JSGlobalData*);
 
         StatementNode(JSGlobalData*);
 
-        void setLoc(int line0, int line1);
+    public:
+        void setLoc(int firstLine, int lastLine);
         int firstLine() const { return lineNo(); }
         int lastLine() const { return m_lastLine; }
 
         int firstLine() const { return lineNo(); }
         int lastLine() const { return m_lastLine; }
 
@@ -227,10 +207,10 @@ namespace JSC {
 
     class NumberNode : public ExpressionNode {
     public:
 
     class NumberNode : public ExpressionNode {
     public:
-        NumberNode(JSGlobalData*, double v);
+        NumberNode(JSGlobalData*, double value);
 
 
-        double value() const { return m_double; }
-        void setValue(double d) { m_double = d; }
+        double value() const { return m_value; }
+        void setValue(double value) { m_value = value; }
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -238,22 +218,23 @@ namespace JSC {
         virtual bool isNumber() const { return true; }
         virtual bool isPure(BytecodeGenerator&) const { return true; }
 
         virtual bool isNumber() const { return true; }
         virtual bool isPure(BytecodeGenerator&) const { return true; }
 
-        double m_double;
+        double m_value;
     };
 
     class StringNode : public ExpressionNode {
     public:
     };
 
     class StringNode : public ExpressionNode {
     public:
-        StringNode(JSGlobalData*, const Identifier& v);
+        StringNode(JSGlobalData*, const Identifier&);
 
         const Identifier& value() { return m_value; }
 
         const Identifier& value() { return m_value; }
-        virtual bool isPure(BytecodeGenerator&) const { return true; }
 
     private:
 
     private:
+        virtual bool isPure(BytecodeGenerator&) const { return true; }
+
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
         
         virtual bool isString() const { return true; }
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
         
         virtual bool isString() const { return true; }
 
-        Identifier m_value;
+        const Identifier& m_value;
     };
     
     class ThrowableExpressionData {
     };
     
     class ThrowableExpressionData {
@@ -284,8 +265,9 @@ namespace JSC {
         uint16_t endOffset() const { return m_endOffset; }
 
     protected:
         uint16_t endOffset() const { return m_endOffset; }
 
     protected:
-        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg);
-        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg, const Identifier&);
+        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* message);
+        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* message, const UString&);
+        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* message, const Identifier&);
 
     private:
         uint32_t m_divot;
 
     private:
         uint32_t m_divot;
@@ -296,8 +278,7 @@ namespace JSC {
     class ThrowableSubExpressionData : public ThrowableExpressionData {
     public:
         ThrowableSubExpressionData()
     class ThrowableSubExpressionData : public ThrowableExpressionData {
     public:
         ThrowableSubExpressionData()
-            : ThrowableExpressionData()
-            , m_subexpressionDivotOffset(0)
+            : m_subexpressionDivotOffset(0)
             , m_subexpressionEndOffset(0)
         {
         }
             , m_subexpressionEndOffset(0)
         {
         }
@@ -326,8 +307,7 @@ namespace JSC {
     class ThrowablePrefixedSubExpressionData : public ThrowableExpressionData {
     public:
         ThrowablePrefixedSubExpressionData()
     class ThrowablePrefixedSubExpressionData : public ThrowableExpressionData {
     public:
         ThrowablePrefixedSubExpressionData()
-            : ThrowableExpressionData()
-            , m_subexpressionDivotOffset(0)
+            : m_subexpressionDivotOffset(0)
             , m_subexpressionStartOffset(0)
         {
         }
             , m_subexpressionStartOffset(0)
         {
         }
@@ -355,13 +335,13 @@ namespace JSC {
 
     class RegExpNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class RegExpNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        RegExpNode(JSGlobalData*, const UString& pattern, const UString& flags);
+        RegExpNode(JSGlobalData*, const Identifier& pattern, const Identifier& flags);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        UString m_pattern;
-        UString m_flags;
+        const Identifier& m_pattern;
+        const Identifier& m_flags;
     };
 
     class ThisNode : public ExpressionNode {
     };
 
     class ThisNode : public ExpressionNode {
@@ -385,11 +365,11 @@ namespace JSC {
         virtual bool isLocation() const { return true; }
         virtual bool isResolveNode() const { return true; }
 
         virtual bool isLocation() const { return true; }
         virtual bool isResolveNode() const { return true; }
 
-        Identifier m_ident;
+        const Identifier& m_ident;
         int32_t m_startOffset;
     };
 
         int32_t m_startOffset;
     };
 
-    class ElementNode : public ParserArenaDeletable {
+    class ElementNode : public ParserArenaFreeable {
     public:
         ElementNode(JSGlobalData*, int elision, ExpressionNode*);
         ElementNode(JSGlobalData*, ElementNode*, int elision, ExpressionNode*);
     public:
         ElementNode(JSGlobalData*, int elision, ExpressionNode*);
         ElementNode(JSGlobalData*, ElementNode*, int elision, ExpressionNode*);
@@ -422,17 +402,18 @@ namespace JSC {
         bool m_optional;
     };
 
         bool m_optional;
     };
 
-    class PropertyNode : public ParserArenaDeletable {
+    class PropertyNode : public ParserArenaFreeable {
     public:
         enum Type { Constant, Getter, Setter };
 
         PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type);
     public:
         enum Type { Constant, Getter, Setter };
 
         PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type);
+        PropertyNode(JSGlobalData*, double name, ExpressionNode* value, Type);
 
         const Identifier& name() const { return m_name; }
 
     private:
         friend class PropertyListNode;
 
         const Identifier& name() const { return m_name; }
 
     private:
         friend class PropertyListNode;
-        Identifier m_name;
+        const Identifier& m_name;
         ExpressionNode* m_assign;
         Type m_type;
     };
         ExpressionNode* m_assign;
         Type m_type;
     };
@@ -492,7 +473,7 @@ namespace JSC {
         virtual bool isDotAccessorNode() const { return true; }
 
         ExpressionNode* m_base;
         virtual bool isDotAccessorNode() const { return true; }
 
         ExpressionNode* m_base;
-        Identifier m_ident;
+        const Identifier& m_ident;
     };
 
     class ArgumentListNode : public Node {
     };
 
     class ArgumentListNode : public Node {
@@ -507,7 +488,7 @@ namespace JSC {
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
     };
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
     };
 
-    class ArgumentsNode : public ParserArenaDeletable {
+    class ArgumentsNode : public ParserArenaFreeable {
     public:
         ArgumentsNode(JSGlobalData*);
         ArgumentsNode(JSGlobalData*, ArgumentListNode*);
     public:
         ArgumentsNode(JSGlobalData*);
         ArgumentsNode(JSGlobalData*, ArgumentListNode*);
@@ -555,7 +536,7 @@ namespace JSC {
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        Identifier m_ident;
+        const Identifier& m_ident;
         ArgumentsNode* m_args;
         size_t m_index; // Used by LocalVarFunctionCallNode.
         size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode
         ArgumentsNode* m_args;
         size_t m_index; // Used by LocalVarFunctionCallNode.
         size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode
@@ -582,7 +563,7 @@ namespace JSC {
 
     protected:
         ExpressionNode* m_base;
 
     protected:
         ExpressionNode* m_base;
-        const Identifier m_ident;
+        const Identifier& m_ident;
         ArgumentsNode* m_args;
     };
 
         ArgumentsNode* m_args;
     };
 
@@ -607,7 +588,7 @@ namespace JSC {
         PrePostResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     protected:
         PrePostResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     protected:
-        const Identifier m_ident;
+        const Identifier& m_ident;
     };
 
     class PostfixResolveNode : public PrePostResolveNode {
     };
 
     class PostfixResolveNode : public PrePostResolveNode {
@@ -640,7 +621,7 @@ namespace JSC {
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         ExpressionNode* m_base;
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         ExpressionNode* m_base;
-        Identifier m_ident;
+        const Identifier& m_ident;
         Operator m_operator;
     };
 
         Operator m_operator;
     };
 
@@ -662,7 +643,7 @@ namespace JSC {
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        Identifier m_ident;
+        const Identifier& m_ident;
     };
 
     class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData {
     };
 
     class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData {
@@ -684,7 +665,7 @@ namespace JSC {
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         ExpressionNode* m_base;
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         ExpressionNode* m_base;
-        Identifier m_ident;
+        const Identifier& m_ident;
     };
 
     class DeleteValueNode : public ExpressionNode {
     };
 
     class DeleteValueNode : public ExpressionNode {
@@ -716,7 +697,7 @@ namespace JSC {
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        Identifier m_ident;
+        const Identifier& m_ident;
     };
 
     class TypeOfValueNode : public ExpressionNode {
     };
 
     class TypeOfValueNode : public ExpressionNode {
@@ -759,7 +740,7 @@ namespace JSC {
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         ExpressionNode* m_base;
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         ExpressionNode* m_base;
-        Identifier m_ident;
+        const Identifier& m_ident;
         Operator m_operator;
     };
 
         Operator m_operator;
     };
 
@@ -780,6 +761,7 @@ namespace JSC {
 
     protected:
         ExpressionNode* expr() { return m_expr; }
 
     protected:
         ExpressionNode* expr() { return m_expr; }
+        const ExpressionNode* expr() const { return m_expr; }
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -811,6 +793,9 @@ namespace JSC {
     class LogicalNotNode : public UnaryOpNode {
     public:
         LogicalNotNode(JSGlobalData*, ExpressionNode*);
     class LogicalNotNode : public UnaryOpNode {
     public:
         LogicalNotNode(JSGlobalData*, ExpressionNode*);
+    private:
+        void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
+        virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); }
     };
 
     class BinaryOpNode : public ExpressionNode {
     };
 
     class BinaryOpNode : public ExpressionNode {
@@ -818,7 +803,7 @@ namespace JSC {
         BinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
         BinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
 
         BinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
         BinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
 
-        RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
+        RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -975,6 +960,8 @@ namespace JSC {
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+        void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
+        virtual bool hasConditionContextCodegen() const { return true; }
 
         ExpressionNode* m_expr1;
         ExpressionNode* m_expr2;
 
         ExpressionNode* m_expr1;
         ExpressionNode* m_expr2;
@@ -1001,7 +988,7 @@ namespace JSC {
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        Identifier m_ident;
+        const Identifier& m_ident;
         ExpressionNode* m_right;
         size_t m_index; // Used by ReadModifyLocalVarNode.
         Operator m_operator;
         ExpressionNode* m_right;
         size_t m_index; // Used by ReadModifyLocalVarNode.
         Operator m_operator;
@@ -1015,7 +1002,7 @@ namespace JSC {
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        Identifier m_ident;
+        const Identifier& m_ident;
         ExpressionNode* m_right;
         size_t m_index; // Used by ReadModifyLocalVarNode.
         bool m_rightHasAssignments;
         ExpressionNode* m_right;
         size_t m_index; // Used by ReadModifyLocalVarNode.
         bool m_rightHasAssignments;
@@ -1058,7 +1045,7 @@ namespace JSC {
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         ExpressionNode* m_base;
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         ExpressionNode* m_base;
-        Identifier m_ident;
+        const Identifier& m_ident;
         ExpressionNode* m_right;
         bool m_rightHasAssignments;
     };
         ExpressionNode* m_right;
         bool m_rightHasAssignments;
     };
@@ -1071,7 +1058,7 @@ namespace JSC {
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         ExpressionNode* m_base;
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         ExpressionNode* m_base;
-        Identifier m_ident;
+        const Identifier& m_ident;
         ExpressionNode* m_right;
         Operator m_operator : 31;
         bool m_rightHasAssignments : 1;
         ExpressionNode* m_right;
         Operator m_operator : 31;
         bool m_rightHasAssignments : 1;
@@ -1091,10 +1078,12 @@ namespace JSC {
     
     typedef Vector<ExpressionNode*, 8> ExpressionVector;
 
     
     typedef Vector<ExpressionNode*, 8> ExpressionVector;
 
-    class CommaNode : public ExpressionNode {
+    class CommaNode : public ExpressionNode, public ParserArenaDeletable {
     public:
         CommaNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2);
 
     public:
         CommaNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2);
 
+        using ParserArenaDeletable::operator new;
+
         void append(ExpressionNode* expr) { m_expressions.append(expr); }
 
     private:
         void append(ExpressionNode* expr) { m_expressions.append(expr); }
 
     private:
@@ -1115,7 +1104,7 @@ namespace JSC {
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
         virtual RegisterID* emitCodeSingle(BytecodeGenerator&);
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
         virtual RegisterID* emitCodeSingle(BytecodeGenerator&);
 
-        Identifier m_ident;
+        const Identifier& m_ident;
 
     public:
         ConstDeclNode* m_next;
 
     public:
         ConstDeclNode* m_next;
@@ -1134,36 +1123,33 @@ namespace JSC {
         ConstDeclNode* m_next;
     };
 
         ConstDeclNode* m_next;
     };
 
-    typedef Vector<StatementNode*> StatementVector;
-
     class SourceElements : public ParserArenaDeletable {
     public:
         SourceElements(JSGlobalData*);
 
         void append(StatementNode*);
     class SourceElements : public ParserArenaDeletable {
     public:
         SourceElements(JSGlobalData*);
 
         void append(StatementNode*);
-        void releaseContentsIntoVector(StatementVector& destination)
-        {
-            ASSERT(destination.isEmpty());
-            m_statements.swap(destination);
-            destination.shrinkToFit();
-        }
+
+        StatementNode* singleStatement() const;
+        StatementNode* lastStatement() const;
+
+        void emitBytecode(BytecodeGenerator&, RegisterID* destination);
 
     private:
 
     private:
-        StatementVector m_statements;
+        Vector<StatementNode*> m_statements;
     };
 
     class BlockNode : public StatementNode {
     public:
     };
 
     class BlockNode : public StatementNode {
     public:
-        BlockNode(JSGlobalData*, SourceElements* children);
+        BlockNode(JSGlobalData*, SourceElements* = 0);
 
 
-        StatementVector& children() { return m_children; }
+        StatementNode* lastStatement() const;
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         virtual bool isBlock() const { return true; }
 
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         virtual bool isBlock() const { return true; }
 
-        StatementVector m_children;
+        SourceElements* m_statements;
     };
 
     class EmptyStatementNode : public StatementNode {
     };
 
     class EmptyStatementNode : public StatementNode {
@@ -1273,7 +1259,7 @@ namespace JSC {
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        Identifier m_ident;
+        const Identifier& m_ident;
         ExpressionNode* m_init;
         ExpressionNode* m_lexpr;
         ExpressionNode* m_expr;
         ExpressionNode* m_init;
         ExpressionNode* m_lexpr;
         ExpressionNode* m_expr;
@@ -1289,7 +1275,7 @@ namespace JSC {
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        Identifier m_ident;
+        const Identifier& m_ident;
     };
 
     class BreakNode : public StatementNode, public ThrowableExpressionData {
     };
 
     class BreakNode : public StatementNode, public ThrowableExpressionData {
@@ -1300,7 +1286,7 @@ namespace JSC {
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        Identifier m_ident;
+        const Identifier& m_ident;
     };
 
     class ReturnNode : public StatementNode, public ThrowableExpressionData {
     };
 
     class ReturnNode : public StatementNode, public ThrowableExpressionData {
@@ -1335,7 +1321,7 @@ namespace JSC {
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        Identifier m_name;
+        const Identifier& m_name;
         StatementNode* m_statement;
     };
 
         StatementNode* m_statement;
     };
 
@@ -1354,16 +1340,16 @@ namespace JSC {
         TryNode(JSGlobalData*, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock);
 
     private:
         TryNode(JSGlobalData*, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock);
 
     private:
-        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0);
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         StatementNode* m_tryBlock;
 
         StatementNode* m_tryBlock;
-        Identifier m_exceptionIdent;
+        const Identifier& m_exceptionIdent;
         StatementNode* m_catchBlock;
         StatementNode* m_finallyBlock;
         bool m_catchHasEval;
     };
 
         StatementNode* m_catchBlock;
         StatementNode* m_finallyBlock;
         bool m_catchHasEval;
     };
 
-    class ParameterNode : public ParserArenaDeletable {
+    class ParameterNode : public ParserArenaFreeable {
     public:
         ParameterNode(JSGlobalData*, const Identifier&);
         ParameterNode(JSGlobalData*, ParameterNode*, const Identifier&);
     public:
         ParameterNode(JSGlobalData*, const Identifier&);
         ParameterNode(JSGlobalData*, ParameterNode*, const Identifier&);
@@ -1372,11 +1358,11 @@ namespace JSC {
         ParameterNode* nextParam() const { return m_next; }
 
     private:
         ParameterNode* nextParam() const { return m_next; }
 
     private:
-        Identifier m_ident;
+        const Identifier& m_ident;
         ParameterNode* m_next;
     };
 
         ParameterNode* m_next;
     };
 
-    struct ScopeNodeData {
+    struct ScopeNodeData : FastAllocBase {
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
@@ -1386,9 +1372,7 @@ namespace JSC {
         VarStack m_varStack;
         FunctionStack m_functionStack;
         int m_numConstants;
         VarStack m_varStack;
         FunctionStack m_functionStack;
         int m_numConstants;
-        StatementVector m_children;
-
-        void mark();
+        SourceElements* m_statements;
     };
 
     class ScopeNode : public StatementNode, public ParserArenaRefCounted {
     };
 
     class ScopeNode : public StatementNode, public ParserArenaRefCounted {
@@ -1399,6 +1383,8 @@ namespace JSC {
         ScopeNode(JSGlobalData*);
         ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants);
 
         ScopeNode(JSGlobalData*);
         ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants);
 
+        using ParserArenaRefCounted::operator new;
+
         void adoptData(std::auto_ptr<ScopeNodeData> data)
         {
             ASSERT(!data->m_arena.contains(this));
         void adoptData(std::auto_ptr<ScopeNodeData> data)
         {
             ASSERT(!data->m_arena.contains(this));
@@ -1424,8 +1410,6 @@ namespace JSC {
         VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; }
         FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; }
 
         VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; }
         FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; }
 
-        StatementVector& children() { ASSERT(m_data); return m_data->m_children; }
-
         int neededConstants()
         {
             ASSERT(m_data);
         int neededConstants()
         {
             ASSERT(m_data);
@@ -1434,33 +1418,13 @@ namespace JSC {
             return m_data->m_numConstants + 2;
         }
 
             return m_data->m_numConstants + 2;
         }
 
-        virtual void mark() { }
+        StatementNode* singleStatement() const;
 
 
-#if ENABLE(JIT)
-        JITCode& generatedJITCode()
-        {
-            ASSERT(m_jitCode);
-            return m_jitCode;
-        }
-
-        ExecutablePool* getExecutablePool()
-        {
-            return m_jitCode.getExecutablePool();
-        }
-
-        void setJITCode(const JITCode jitCode)
-        {
-            m_jitCode = jitCode;
-        }
-#endif
+        void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination);
 
     protected:
         void setSource(const SourceCode& source) { m_source = source; }
 
 
     protected:
         void setSource(const SourceCode& source) { m_source = source; }
 
-#if ENABLE(JIT)
-        JITCode m_jitCode;
-#endif
-
     private:
         OwnPtr<ScopeNodeData> m_data;
         CodeFeatures m_features;
     private:
         OwnPtr<ScopeNodeData> m_data;
         CodeFeatures m_features;
@@ -1471,187 +1435,99 @@ namespace JSC {
     public:
         static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
 
     public:
         static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
 
-        ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain) 
-        {
-            if (!m_code)
-                generateBytecode(scopeChain);
-            return *m_code;
-        }
-
-#if ENABLE(JIT)
-        JITCode& jitCode(ScopeChainNode* scopeChain)
-        {
-            if (!m_jitCode)
-                generateJITCode(scopeChain);
-            return m_jitCode;
-        }
-#endif
+        static const bool scopeIsFunction = false;
 
     private:
         ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
 
 
     private:
         ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
 
-        void generateBytecode(ScopeChainNode*);
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
-
-#if ENABLE(JIT)
-        void generateJITCode(ScopeChainNode*);
-#endif
-
-        OwnPtr<ProgramCodeBlock> m_code;
     };
 
     class EvalNode : public ScopeNode {
     public:
         static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
 
     };
 
     class EvalNode : public ScopeNode {
     public:
         static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
 
-        EvalCodeBlock& bytecode(ScopeChainNode* scopeChain) 
-        {
-            if (!m_code)
-                generateBytecode(scopeChain);
-            return *m_code;
-        }
-
-        EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*);
-
-        virtual void mark();
-
-#if ENABLE(JIT)
-        JITCode& jitCode(ScopeChainNode* scopeChain)
-        {
-            if (!m_jitCode)
-                generateJITCode(scopeChain);
-            return m_jitCode;
-        }
-#endif
+        static const bool scopeIsFunction = false;
 
     private:
         EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
 
 
     private:
         EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
 
-        void generateBytecode(ScopeChainNode*);
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+    };
 
 
-#if ENABLE(JIT)
-        void generateJITCode(ScopeChainNode*);
-#endif
-        
-        OwnPtr<EvalCodeBlock> m_code;
+    class FunctionParameters : public Vector<Identifier>, public RefCounted<FunctionParameters> {
+    public:
+        static PassRefPtr<FunctionParameters> create(ParameterNode* firstParameter) { return adoptRef(new FunctionParameters(firstParameter)); }
+
+    private:
+        FunctionParameters(ParameterNode*);
     };
 
     class FunctionBodyNode : public ScopeNode {
     };
 
     class FunctionBodyNode : public ScopeNode {
-        friend class JIT;
     public:
     public:
-#if ENABLE(JIT)
-        static PassRefPtr<FunctionBodyNode> createNativeThunk(JSGlobalData*);
-#endif
         static FunctionBodyNode* create(JSGlobalData*);
         static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
         static FunctionBodyNode* create(JSGlobalData*);
         static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
-        virtual ~FunctionBodyNode();
 
 
-        const Identifier* parameters() const { return m_parameters; }
-        size_t parameterCount() const { return m_parameterCount; }
-        UString paramString() const ;
-        Identifier* copyParameters();
+        FunctionParameters* parameters() const { return m_parameters.get(); }
+        size_t parameterCount() const { return m_parameters->size(); }
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        bool isGenerated() const
-        {
-            return m_code;
-        }
-
-        bool isHostFunction() const;
-
-        virtual void mark();
-
-        void finishParsing(const SourceCode&, ParameterNode*);
-        void finishParsing(Identifier* parameters, size_t parameterCount);
+        void finishParsing(const SourceCode&, ParameterNode*, const Identifier&);
+        void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&);
         
         
-        UString toSourceString() const { return source().toString(); }
+        const Identifier& ident() { return m_ident; }
 
 
-        CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*);
-#if ENABLE(JIT)
-        JITCode& jitCode(ScopeChainNode* scopeChain)
-        {
-            if (!m_jitCode)
-                generateJITCode(scopeChain);
-            return m_jitCode;
-        }
-#endif
+        static const bool scopeIsFunction = true;
 
 
-        CodeBlock& bytecode(ScopeChainNode* scopeChain) 
-        {
-            ASSERT(scopeChain);
-            if (!m_code)
-                generateBytecode(scopeChain);
-            return *m_code;
-        }
-        
-        CodeBlock& generatedBytecode()
-        {
-            ASSERT(m_code);
-            return *m_code;
-        }
-        
     private:
         FunctionBodyNode(JSGlobalData*);
         FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
 
     private:
         FunctionBodyNode(JSGlobalData*);
         FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
 
-        void generateBytecode(ScopeChainNode*);
-#if ENABLE(JIT)
-        void generateJITCode(ScopeChainNode*);
-#endif
-        Identifier* m_parameters;
-        size_t m_parameterCount;
-        OwnPtr<CodeBlock> m_code;
+        Identifier m_ident;
+        RefPtr<FunctionParameters> m_parameters;
     };
 
     };
 
-    class FuncExprNode : public ExpressionNode, public ParserArenaRefCounted {
+    class FuncExprNode : public ExpressionNode {
     public:
         FuncExprNode(JSGlobalData*, const Identifier&, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0);
 
     public:
         FuncExprNode(JSGlobalData*, const Identifier&, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0);
 
-        JSFunction* makeFunction(ExecState*, ScopeChainNode*);
-
-        FunctionBodyNode* body() { return m_body.get(); }
+        FunctionBodyNode* body() { return m_body; }
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         virtual bool isFuncExprNode() const { return true; } 
 
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
         virtual bool isFuncExprNode() const { return true; } 
 
-        Identifier m_ident;
-        RefPtr<FunctionBodyNode> m_body;
+        FunctionBodyNode* m_body;
     };
 
     };
 
-    class FuncDeclNode : public StatementNode, public ParserArenaRefCounted {
+    class FuncDeclNode : public StatementNode {
     public:
         FuncDeclNode(JSGlobalData*, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0);
 
     public:
         FuncDeclNode(JSGlobalData*, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0);
 
-        JSFunction* makeFunction(ExecState*, ScopeChainNode*);
-
-        Identifier m_ident;
-
-        FunctionBodyNode* body() { return m_body.get(); }
+        FunctionBodyNode* body() { return m_body; }
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
-        RefPtr<FunctionBodyNode> m_body;
+        FunctionBodyNode* m_body;
     };
 
     };
 
-    class CaseClauseNode : public ParserArenaDeletable {
+    class CaseClauseNode : public ParserArenaFreeable {
     public:
     public:
-        CaseClauseNode(JSGlobalData*, ExpressionNode*);
-        CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements*);
+        CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements* = 0);
 
         ExpressionNode* expr() const { return m_expr; }
 
         ExpressionNode* expr() const { return m_expr; }
-        StatementVector& children() { return m_children; }
+
+        void emitBytecode(BytecodeGenerator&, RegisterID* destination);
 
     private:
         ExpressionNode* m_expr;
 
     private:
         ExpressionNode* m_expr;
-        StatementVector m_children;
+        SourceElements* m_statements;
     };
 
     };
 
-    class ClauseListNode : public ParserArenaDeletable {
+    class ClauseListNode : public ParserArenaFreeable {
     public:
         ClauseListNode(JSGlobalData*, CaseClauseNode*);
         ClauseListNode(JSGlobalData*, ClauseListNode*, CaseClauseNode*);
     public:
         ClauseListNode(JSGlobalData*, CaseClauseNode*);
         ClauseListNode(JSGlobalData*, ClauseListNode*, CaseClauseNode*);
@@ -1664,11 +1540,11 @@ namespace JSC {
         ClauseListNode* m_next;
     };
 
         ClauseListNode* m_next;
     };
 
-    class CaseBlockNode : public ParserArenaDeletable {
+    class CaseBlockNode : public ParserArenaFreeable {
     public:
         CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2);
 
     public:
         CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2);
 
-        RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0);
+        RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination);
 
     private:
         SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num);
 
     private:
         SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num);
index 96f4ae6ae2ad5c82d7bb27a42e9e3a98ba6f2c4f..4c046d0627903d0ff78bbaadd456994f52fb9ad8 100644 (file)
@@ -53,7 +53,7 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
     *errMsg = 0;
 
     Lexer& lexer = *globalData->lexer;
     *errMsg = 0;
 
     Lexer& lexer = *globalData->lexer;
-    lexer.setCode(*m_source);
+    lexer.setCode(*m_source, m_arena);
 
     int parseError = jscyyparse(globalData);
     bool lexError = lexer.sawError();
 
     int parseError = jscyyparse(globalData);
     bool lexError = lexer.sawError();
@@ -67,33 +67,6 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
     }
 }
 
     }
 }
 
-void Parser::reparseInPlace(JSGlobalData* globalData, FunctionBodyNode* functionBodyNode)
-{
-    ASSERT(!functionBodyNode->data());
-
-    m_source = &functionBodyNode->source();
-    globalData->lexer->setIsReparsing();
-    parse(globalData, 0, 0);
-    ASSERT(m_sourceElements);
-
-    functionBodyNode->adoptData(std::auto_ptr<ScopeNodeData>(new ScopeNodeData(globalData->parser->arena(),
-        m_sourceElements,
-        m_varDeclarations ? &m_varDeclarations->data : 0, 
-        m_funcDeclarations ? &m_funcDeclarations->data : 0,
-        m_numConstants)));
-    bool usesArguments = functionBodyNode->usesArguments();
-    functionBodyNode->setFeatures(m_features);
-    if (usesArguments && !functionBodyNode->usesArguments())
-        functionBodyNode->setUsesArguments();
-
-    ASSERT(globalData->parser->arena().isEmpty());
-
-    m_source = 0;
-    m_sourceElements = 0;
-    m_varDeclarations = 0;
-    m_funcDeclarations = 0;
-}
-
 void Parser::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, 
                               ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants)
 {
 void Parser::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, 
                               ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants)
 {
index 6f4c2b7d4ee5b7969b75337c93b73eeb8b9e464e..894f709828e50217d13be2134efeae0eb4fc660a 100644 (file)
 #define Parser_h
 
 #include "Debugger.h"
 #define Parser_h
 
 #include "Debugger.h"
+#include "Executable.h"
+#include "JSGlobalObject.h"
+#include "Lexer.h"
 #include "Nodes.h"
 #include "Nodes.h"
+#include "ParserArena.h"
 #include "SourceProvider.h"
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
 #include "SourceProvider.h"
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
@@ -39,11 +43,10 @@ namespace JSC {
 
     template <typename T> struct ParserArenaData : ParserArenaDeletable { T data; };
 
 
     template <typename T> struct ParserArenaData : ParserArenaDeletable { T data; };
 
-    class Parser : Noncopyable {
+    class Parser : public Noncopyable {
     public:
     public:
-        template <class ParsedNode> PassRefPtr<ParsedNode> parse(ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
-        template <class ParsedNode> PassRefPtr<ParsedNode> reparse(JSGlobalData*, ParsedNode*);
-        void reparseInPlace(JSGlobalData*, FunctionBodyNode*);
+        template <class ParsedNode>
+        PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, Debugger*, ExecState*, const SourceCode& source, int* errLine = 0, UString* errMsg = 0);
 
         void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, 
                               ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants);
 
         void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, 
                               ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants);
@@ -63,55 +66,35 @@ namespace JSC {
         int m_numConstants;
     };
 
         int m_numConstants;
     };
 
-    template <class ParsedNode> PassRefPtr<ParsedNode> Parser::parse(ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
+    template <class ParsedNode>
+    PassRefPtr<ParsedNode> Parser::parse(JSGlobalData* globalData, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, int* errLine, UString* errMsg)
     {
         m_source = &source;
     {
         m_source = &source;
-        parse(&exec->globalData(), errLine, errMsg);
-        RefPtr<ParsedNode> result;
-        if (m_sourceElements) {
-            result = ParsedNode::create(&exec->globalData(),
-                                         m_sourceElements,
-                                         m_varDeclarations ? &m_varDeclarations->data : 0, 
-                                         m_funcDeclarations ? &m_funcDeclarations->data : 0,
-                                         *m_source,
-                                         m_features,
-                                         m_numConstants);
-            result->setLoc(m_source->firstLine(), m_lastLine);
-        }
-
-        m_arena.reset();
-
-        m_source = 0;
-        m_varDeclarations = 0;
-        m_funcDeclarations = 0;
+        if (ParsedNode::scopeIsFunction)
+            globalData->lexer->setIsReparsing();
+        parse(globalData, errLine, errMsg);
 
 
-        if (debugger)
-            debugger->sourceParsed(exec, source, *errLine, *errMsg);
-        return result.release();
-    }
-
-    template <class ParsedNode> PassRefPtr<ParsedNode> Parser::reparse(JSGlobalData* globalData, ParsedNode* oldParsedNode)
-    {
-        m_source = &oldParsedNode->source();
-        parse(globalData, 0, 0);
         RefPtr<ParsedNode> result;
         if (m_sourceElements) {
             result = ParsedNode::create(globalData,
         RefPtr<ParsedNode> result;
         if (m_sourceElements) {
             result = ParsedNode::create(globalData,
-                                        m_sourceElements,
-                                        m_varDeclarations ? &m_varDeclarations->data : 0, 
-                                        m_funcDeclarations ? &m_funcDeclarations->data : 0,
-                                        *m_source,
-                                        oldParsedNode->features(),
-                                        m_numConstants);
+            m_sourceElements,
+            m_varDeclarations ? &m_varDeclarations->data : 0,
+            m_funcDeclarations ? &m_funcDeclarations->data : 0,
+            source,
+            m_features,
+            m_numConstants);
             result->setLoc(m_source->firstLine(), m_lastLine);
         }
 
         m_arena.reset();
 
         m_source = 0;
             result->setLoc(m_source->firstLine(), m_lastLine);
         }
 
         m_arena.reset();
 
         m_source = 0;
+        m_sourceElements = 0;
         m_varDeclarations = 0;
         m_funcDeclarations = 0;
 
         m_varDeclarations = 0;
         m_funcDeclarations = 0;
 
+        if (debugger && !ParsedNode::scopeIsFunction)
+            debugger->sourceParsed(debuggerExecState, source, *errLine, *errMsg);
         return result.release();
     }
 
         return result.release();
     }
 
index 261750668efd779f14797ab6c3cabec5c4b24ef5..a8e81595384a2c882cee7b7aab9bd52b2b2c95de 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
+ParserArena::ParserArena()
+    : m_freeableMemory(0)
+    , m_freeablePoolEnd(0)
+    , m_identifierArena(new IdentifierArena)
+{
+}
+
+inline void* ParserArena::freeablePool()
+{
+    ASSERT(m_freeablePoolEnd);
+    return m_freeablePoolEnd - freeablePoolSize;
+}
+
+inline void ParserArena::deallocateObjects()
+{
+    if (m_freeablePoolEnd)
+        fastFree(freeablePool());
+
+    size_t size = m_freeablePools.size();
+    for (size_t i = 0; i < size; ++i)
+        fastFree(m_freeablePools[i]);
+
+    size = m_deletableObjects.size();
+    for (size_t i = 0; i < size; ++i) {
+        ParserArenaDeletable* object = m_deletableObjects[i];
+        object->~ParserArenaDeletable();
+        fastFree(object);
+    }
+}
+
 ParserArena::~ParserArena()
 {
 ParserArena::~ParserArena()
 {
-    deleteAllValues(m_deletableObjects);
+    deallocateObjects();
 }
 
 bool ParserArena::contains(ParserArenaRefCounted* object) const
 }
 
 bool ParserArena::contains(ParserArenaRefCounted* object) const
@@ -52,9 +82,43 @@ void ParserArena::removeLast()
 
 void ParserArena::reset()
 {
 
 void ParserArena::reset()
 {
-    deleteAllValues(m_deletableObjects);
-    m_deletableObjects.shrink(0);
-    m_refCountedObjects.shrink(0);
+    // Since this code path is used only when parsing fails, it's not bothering to reuse
+    // any of the memory the arena allocated. We could improve that later if we want to
+    // efficiently reuse the same arena.
+
+    deallocateObjects();
+
+    m_freeableMemory = 0;
+    m_freeablePoolEnd = 0;
+    m_identifierArena->clear();
+    m_freeablePools.clear();
+    m_deletableObjects.clear();
+    m_refCountedObjects.clear();
+}
+
+void ParserArena::allocateFreeablePool()
+{
+    if (m_freeablePoolEnd)
+        m_freeablePools.append(freeablePool());
+
+    char* pool = static_cast<char*>(fastMalloc(freeablePoolSize));
+    m_freeableMemory = pool;
+    m_freeablePoolEnd = pool + freeablePoolSize;
+    ASSERT(freeablePool() == pool);
+}
+
+bool ParserArena::isEmpty() const
+{
+    return !m_freeablePoolEnd
+        && m_identifierArena->isEmpty()
+        && m_freeablePools.isEmpty()
+        && m_deletableObjects.isEmpty()
+        && m_refCountedObjects.isEmpty();
+}
+
+void ParserArena::derefWithArena(PassRefPtr<ParserArenaRefCounted> object)
+{
+    m_refCountedObjects.append(object);
 }
 
 }
 }
 
 }
index 66c8529abe174362182a93f6041d4cf0a7289fb6..eef8e939394c1cff51222066000607f7d07284d7 100644 (file)
 #ifndef ParserArena_h
 #define ParserArena_h
 
 #ifndef ParserArena_h
 #define ParserArena_h
 
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
+#include "Identifier.h"
+#include <wtf/SegmentedVector.h>
 
 namespace JSC {
 
     class ParserArenaDeletable;
     class ParserArenaRefCounted;
 
 
 namespace JSC {
 
     class ParserArenaDeletable;
     class ParserArenaRefCounted;
 
-    class ParserArena {
+    class IdentifierArena : public FastAllocBase {
     public:
     public:
+        ALWAYS_INLINE const Identifier& makeIdentifier(JSGlobalData*, const UChar* characters, size_t length);
+        const Identifier& makeNumericIdentifier(JSGlobalData*, double number);
+
+        void clear() { m_identifiers.clear(); }
+        bool isEmpty() const { return m_identifiers.isEmpty(); }
+
+    private:
+        typedef SegmentedVector<Identifier, 64> IdentifierVector;
+        IdentifierVector m_identifiers;
+    };
+
+    ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(JSGlobalData* globalData, const UChar* characters, size_t length)
+    {
+        m_identifiers.append(Identifier(globalData, characters, length));
+        return m_identifiers.last();
+    }
+
+    inline const Identifier& IdentifierArena::makeNumericIdentifier(JSGlobalData* globalData, double number)
+    {
+        m_identifiers.append(Identifier(globalData, UString::from(number)));
+        return m_identifiers.last();
+    }
+
+    class ParserArena : Noncopyable {
+    public:
+        ParserArena();
+        ~ParserArena();
+
         void swap(ParserArena& otherArena)
         {
         void swap(ParserArena& otherArena)
         {
+            std::swap(m_freeableMemory, otherArena.m_freeableMemory);
+            std::swap(m_freeablePoolEnd, otherArena.m_freeablePoolEnd);
+            m_identifierArena.swap(otherArena.m_identifierArena);
+            m_freeablePools.swap(otherArena.m_freeablePools);
             m_deletableObjects.swap(otherArena.m_deletableObjects);
             m_refCountedObjects.swap(otherArena.m_refCountedObjects);
         }
             m_deletableObjects.swap(otherArena.m_deletableObjects);
             m_refCountedObjects.swap(otherArena.m_refCountedObjects);
         }
-        ~ParserArena();
 
 
-        void deleteWithArena(ParserArenaDeletable* object) { m_deletableObjects.append(object); }
-        void derefWithArena(PassRefPtr<ParserArenaRefCounted> object) { m_refCountedObjects.append(object); }
+        void* allocateFreeable(size_t size)
+        {
+            ASSERT(size);
+            ASSERT(size <= freeablePoolSize);
+            size_t alignedSize = alignSize(size);
+            ASSERT(alignedSize <= freeablePoolSize);
+            if (UNLIKELY(static_cast<size_t>(m_freeablePoolEnd - m_freeableMemory) < alignedSize))
+                allocateFreeablePool();
+            void* block = m_freeableMemory;
+            m_freeableMemory += alignedSize;
+            return block;
+        }
+
+        void* allocateDeletable(size_t size)
+        {
+            ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(fastMalloc(size));
+            m_deletableObjects.append(deletable);
+            return deletable;
+        }
 
 
+        void derefWithArena(PassRefPtr<ParserArenaRefCounted>);
         bool contains(ParserArenaRefCounted*) const;
         ParserArenaRefCounted* last() const;
         void removeLast();
 
         bool contains(ParserArenaRefCounted*) const;
         ParserArenaRefCounted* last() const;
         void removeLast();
 
-        bool isEmpty() const { return m_deletableObjects.isEmpty() && m_refCountedObjects.isEmpty(); }
+        bool isEmpty() const;
         void reset();
 
         void reset();
 
+        IdentifierArena& identifierArena() { return *m_identifierArena; }
+
     private:
     private:
+        static const size_t freeablePoolSize = 8000;
+
+        static size_t alignSize(size_t size)
+        {
+            return (size + sizeof(WTF::AllocAlignmentInteger) - 1) & ~(sizeof(WTF::AllocAlignmentInteger) - 1);
+        }
+
+        void* freeablePool();
+        void allocateFreeablePool();
+        void deallocateObjects();
+
+        char* m_freeableMemory;
+        char* m_freeablePoolEnd;
+
+        OwnPtr<IdentifierArena> m_identifierArena;
+        Vector<void*> m_freeablePools;
         Vector<ParserArenaDeletable*> m_deletableObjects;
         Vector<RefPtr<ParserArenaRefCounted> > m_refCountedObjects;
     };
         Vector<ParserArenaDeletable*> m_deletableObjects;
         Vector<RefPtr<ParserArenaRefCounted> > m_refCountedObjects;
     };
index 84360b84c646890d32862e0baa8d615ac4d7a436..9ba4da3d80678f48de6d1bfa269330fa448842ba 100644 (file)
@@ -37,7 +37,8 @@ namespace JSC {
     class SourceCode {
     public:
         SourceCode()
     class SourceCode {
     public:
         SourceCode()
-            : m_startChar(0)
+            : m_provider(0)
+            , m_startChar(0)
             , m_endChar(0)
             , m_firstLine(0)
         {
             , m_endChar(0)
             , m_firstLine(0)
         {
index 8a2d1401b48a7bf930220b7e10a3c800b84ae37c..669b948ffc91636ca63bb85d3a66c7a0368fb379 100755 (executable)
@@ -244,7 +244,7 @@ sub readHeaderValues()
  
     my ($fh, $tempFile) = tempfile(
         basename($0) . "-XXXXXXXX",
  
     my ($fh, $tempFile) = tempfile(
         basename($0) . "-XXXXXXXX",
-        DIR => File::Spec->tmpdir,
+        DIR => File::Spec->tmpdir(),
         SUFFIX => ".in",
         UNLINK => 0,
     );
         SUFFIX => ".in",
         UNLINK => 0,
     );
@@ -269,4 +269,5 @@ sub readHeaderValues()
     
     eval $content;
     die "$@" if $@;
     
     eval $content;
     die "$@" if $@;
+    unlink $tempFile;
 }
 }
index c33c67ce97ae6da38015e99385200aa46ec86a40..4f59e17f4d917660328a8c50bd5d08325970cf47 100644 (file)
@@ -3,8 +3,6 @@ VPATH += $$PWD
 INCLUDEPATH += $$PWD $$OUTPUT_DIR/JavaScriptCore/tmp
 DEPENDPATH += $$PWD
 
 INCLUDEPATH += $$PWD $$OUTPUT_DIR/JavaScriptCore/tmp
 DEPENDPATH += $$PWD
 
-isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = tmp
-
 SOURCES += \
     pcre_compile.cpp \
     pcre_exec.cpp \
 SOURCES += \
     pcre_compile.cpp \
     pcre_exec.cpp \
@@ -12,24 +10,3 @@ SOURCES += \
     pcre_ucp_searchfuncs.cpp \
     pcre_xclass.cpp
 
     pcre_ucp_searchfuncs.cpp \
     pcre_xclass.cpp
 
-!CONFIG(QTDIR_build) {
-    defineTest(addExtraCompiler) {
-        QMAKE_EXTRA_COMPILERS += $$1
-        generated_files.depends += compiler_$${1}_make_all
-        export(QMAKE_EXTRA_COMPILERS)
-        export(generated_files.depends)
-        return(true)
-    }
-}
-
-# GENERATOR: "chartables.c": compile and execute the chartables generator (and add it to sources)
-win32-msvc*|wince*: PREPROCESSOR = "--preprocessor=\"$$QMAKE_CC /E\""
-DFTABLES = $$PWD/dftables
-ctgen.input = DFTABLES
-ctgen.output = $$GENERATED_SOURCES_DIR/chartables.c
-ctgen.commands = perl $$DFTABLES ${QMAKE_FILE_OUT} $$PREPROCESSOR
-ctgen.CONFIG += target_predeps no_link
-ctgen.variable_out = GENERATED_SOURCES
-ctgen.dependency_type = TYPE_C
-ctgen.clean = ${QMAKE_FILE_OUT} ${QMAKE_VAR_GENERATED_SOURCES_DIR}${QMAKE_FILE_BASE}
-addExtraCompiler(ctgen)
index af770f38a983c3ccb78f00b289c7ff957ae499e3..8ca2eb4b79efddf053cdfc4b56733f96f9e12132 100644 (file)
@@ -112,7 +112,7 @@ struct BracketChainNode {
     const UChar* bracketStart;
 };
 
     const UChar* bracketStart;
 };
 
-struct MatchFrame {
+struct MatchFrame : FastAllocBase {
     ReturnLocation returnLocation;
     struct MatchFrame* previousFrame;
     
     ReturnLocation returnLocation;
     struct MatchFrame* previousFrame;
     
@@ -2164,14 +2164,14 @@ void Histogram::add(const JSRegExp* re, double elapsedTime)
 
 HistogramTimeLogger::HistogramTimeLogger(const JSRegExp* re)
     : m_re(re)
 
 HistogramTimeLogger::HistogramTimeLogger(const JSRegExp* re)
     : m_re(re)
-    , m_startTime(getCurrentUTCTimeWithMicroseconds())
+    , m_startTime(currentTimeMS())
 {
 }
 
 HistogramTimeLogger::~HistogramTimeLogger()
 {
     static Histogram histogram;
 {
 }
 
 HistogramTimeLogger::~HistogramTimeLogger()
 {
     static Histogram histogram;
-    histogram.add(m_re, getCurrentUTCTimeWithMicroseconds() - m_startTime);
+    histogram.add(m_re, currentTimeMS() - m_startTime);
 }
 
 #endif
 }
 
 #endif
diff --git a/profiler/HeavyProfile.cpp b/profiler/HeavyProfile.cpp
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/profiler/HeavyProfile.h b/profiler/HeavyProfile.h
deleted file mode 100644 (file)
index e69de29..0000000
index 1a061cb9cb699ea4fb677456c22c15bb00d5eae5..17d37d7071d9900a3c391e8b317dc83846e77835 100644 (file)
@@ -27,6 +27,7 @@
 #include "ProfileGenerator.h"
 
 #include "CallFrame.h"
 #include "ProfileGenerator.h"
 
 #include "CallFrame.h"
+#include "CodeBlock.h"
 #include "JSGlobalObject.h"
 #include "JSStringRef.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSStringRef.h"
 #include "JSFunction.h"
@@ -62,7 +63,7 @@ void ProfileGenerator::addParentForConsoleStart(ExecState* exec)
     JSValue function;
 
     exec->interpreter()->retrieveLastCaller(exec, lineNumber, sourceID, sourceURL, function);
     JSValue function;
 
     exec->interpreter()->retrieveLastCaller(exec, lineNumber, sourceID, sourceURL, function);
-    m_currentNode = ProfileNode::create(Profiler::createCallIdentifier(&exec->globalData(), function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get());
+    m_currentNode = ProfileNode::create(Profiler::createCallIdentifier(exec, function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get());
     m_head->insertNode(m_currentNode.get());
 }
 
     m_head->insertNode(m_currentNode.get());
 }
 
index cccb502d43d2ae28ce2e366a2c1af86b4dae3cd4..82149b33d61675d410ddb0ada5d1c142465fd907 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class CallIdentifier;
     class ExecState;
     class Profile;
     class ProfileNode;
     class UString;
     class ExecState;
     class Profile;
     class ProfileNode;
     class UString;
+    struct CallIdentifier;    
 
     class ProfileGenerator : public RefCounted<ProfileGenerator>  {
     public:
 
     class ProfileGenerator : public RefCounted<ProfileGenerator>  {
     public:
index 19050aa0c60a6f39e5073c1caa43d43d3af15df0..fb126b3febd5e84a688a767b66843da6d0adef69 100644 (file)
 #include <stdio.h>
 #include <wtf/DateMath.h>
 
 #include <stdio.h>
 #include <wtf/DateMath.h>
 
-#if PLATFORM(WIN_OS)
+#if OS(WINDOWS)
 #include <windows.h>
 #endif
 
 #include <windows.h>
 #endif
 
+using namespace WTF;
+
 namespace JSC {
 
 static double getCount()
 {
 namespace JSC {
 
 static double getCount()
 {
-#if PLATFORM(WIN_OS)
+#if OS(WINDOWS)
     static LARGE_INTEGER frequency = {0};
     if (!frequency.QuadPart)
         QueryPerformanceFrequency(&frequency);
     static LARGE_INTEGER frequency = {0};
     if (!frequency.QuadPart)
         QueryPerformanceFrequency(&frequency);
@@ -49,7 +51,7 @@ static double getCount()
     QueryPerformanceCounter(&counter);
     return static_cast<double>(counter.QuadPart) / frequency.QuadPart;
 #else
     QueryPerformanceCounter(&counter);
     return static_cast<double>(counter.QuadPart) / frequency.QuadPart;
 #else
-    return WTF::getCurrentUTCTimeWithMicroseconds();
+    return currentTimeMS();
 #endif
 }
 
 #endif
 }
 
index e103fd19fb9f0ea1edae8b5def6097a7c415a372..fe8727a4bf3b9f29029c5c156fd6b5e95d144db6 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "CommonIdentifiers.h"
 #include "CallFrame.h"
 
 #include "CommonIdentifiers.h"
 #include "CallFrame.h"
+#include "CodeBlock.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "Nodes.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "Nodes.h"
@@ -45,7 +46,7 @@ static const char* GlobalCodeExecution = "(program)";
 static const char* AnonymousFunction = "(anonymous function)";
 static unsigned ProfilesUID = 0;
 
 static const char* AnonymousFunction = "(anonymous function)";
 static unsigned ProfilesUID = 0;
 
-static CallIdentifier createCallIdentifierFromFunctionImp(JSGlobalData*, JSFunction*);
+static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSFunction*);
 
 Profiler* Profiler::s_sharedProfiler = 0;
 Profiler* Profiler::s_sharedEnabledProfilerReference = 0;
 
 Profiler* Profiler::s_sharedProfiler = 0;
 Profiler* Profiler::s_sharedEnabledProfilerReference = 0;
@@ -108,14 +109,14 @@ void Profiler::willExecute(ExecState* exec, JSValue function)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(&exec->globalData(), function, "", 0), exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup());
 }
 
 void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
 }
 
 void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    CallIdentifier callIdentifier = createCallIdentifier(&exec->globalData(), JSValue(), sourceURL, startingLineNumber);
+    CallIdentifier callIdentifier = createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber);
 
     dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup());
 }
 
     dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup());
 }
@@ -124,36 +125,37 @@ void Profiler::didExecute(ExecState* exec, JSValue function)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), function, "", 0), exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup());
 }
 
 void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
 }
 
 void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup());
 }
 
 }
 
-CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValue function, const UString& defaultSourceURL, int defaultLineNumber)
+CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const UString& defaultSourceURL, int defaultLineNumber)
 {
 {
-    if (!function)
+    if (!functionValue)
         return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
         return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
-    if (!function.isObject())
+    if (!functionValue.isObject())
         return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
         return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
-    if (asObject(function)->inherits(&JSFunction::info)) {
-        JSFunction* func = asFunction(function);
-        if (!func->isHostFunction())
-            return createCallIdentifierFromFunctionImp(globalData, func);
+    if (asObject(functionValue)->inherits(&JSFunction::info)) {
+        JSFunction* function = asFunction(functionValue);
+        if (!function->executable()->isHostFunction())
+            return createCallIdentifierFromFunctionImp(exec, function);
     }
     }
-    if (asObject(function)->inherits(&InternalFunction::info))
-        return CallIdentifier(static_cast<InternalFunction*>(asObject(function))->name(globalData), defaultSourceURL, defaultLineNumber);
-    return CallIdentifier("(" + asObject(function)->className() + " object)", defaultSourceURL, defaultLineNumber);
+    if (asObject(functionValue)->inherits(&InternalFunction::info))
+        return CallIdentifier(static_cast<InternalFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber);
+    return CallIdentifier(makeString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber);
 }
 
 }
 
-CallIdentifier createCallIdentifierFromFunctionImp(JSGlobalData* globalData, JSFunction* function)
+CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSFunction* function)
 {
 {
-    const UString& name = function->calculatedDisplayName(globalData);
-    return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->body()->sourceURL(), function->body()->lineNo());
+    ASSERT(!function->isHostFunction());
+    const UString& name = function->calculatedDisplayName(exec);
+    return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->jsExecutable()->sourceURL(), function->jsExecutable()->lineNo());
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index b37f6135619bd3c3baf947b1c2279fc17a90b862..4b8b4a019f0d0c0570c74e3b4b07b73e429f0a4b 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class CallIdentifier;
     class ExecState;
     class JSGlobalData;
     class JSObject;
     class JSValue;
     class ProfileGenerator;
     class UString;
     class ExecState;
     class JSGlobalData;
     class JSObject;
     class JSValue;
     class ProfileGenerator;
     class UString;
+    struct CallIdentifier;    
 
 
-    class Profiler {
+    class Profiler : public FastAllocBase {
     public:
         static Profiler** enabledProfilerReference()
         {
     public:
         static Profiler** enabledProfilerReference()
         {
@@ -52,7 +52,7 @@ namespace JSC {
         }
 
         static Profiler* profiler(); 
         }
 
         static Profiler* profiler(); 
-        static CallIdentifier createCallIdentifier(JSGlobalData*, JSValue, const UString& sourceURL, int lineNumber);
+        static CallIdentifier createCallIdentifier(ExecState* exec, JSValue, const UString& sourceURL, int lineNumber);
 
         void startProfiling(ExecState*, const UString& title);
         PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title);
 
         void startProfiling(ExecState*, const UString& title);
         PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title);
index 251c2e3eb1b8b96041e48b0ff532c113f00a1e54..29f075c421d2887f7c9c3b1e4eb6b1c7fc9daf9d 100644 (file)
 #import "JSProfilerPrivate.h"
 #import "JSRetainPtr.h"
 #import <Foundation/Foundation.h>
 #import "JSProfilerPrivate.h"
 #import "JSRetainPtr.h"
 #import <Foundation/Foundation.h>
+
 #if PLATFORM(IPHONE_SIMULATOR)
 #import <Foundation/NSDistributedNotificationCenter.h>
 #endif
 
 #if PLATFORM(IPHONE_SIMULATOR)
 #import <Foundation/NSDistributedNotificationCenter.h>
 #endif
 
-
 @interface ProfilerServer : NSObject {
 @private
     NSString *_serverName;
 @interface ProfilerServer : NSObject {
 @private
     NSString *_serverName;
diff --git a/profiler/TreeProfile.cpp b/profiler/TreeProfile.cpp
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/profiler/TreeProfile.h b/profiler/TreeProfile.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/qt/api/QtScript.pro b/qt/api/QtScript.pro
new file mode 100644 (file)
index 0000000..c87eaf4
--- /dev/null
@@ -0,0 +1,36 @@
+TARGET     = QtScript
+TEMPLATE   = lib
+QT         = core
+
+INCLUDEPATH += $$PWD
+
+CONFIG += building-libs
+
+isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = ../../generated
+CONFIG(debug, debug|release) {
+    OBJECTS_DIR = obj/debug
+} else { # Release
+    OBJECTS_DIR = obj/release
+}
+
+include($$PWD/../../../WebKit.pri)
+include($$PWD/../../JavaScriptCore.pri)
+
+INCLUDEPATH += $$PWD/../../API
+
+SOURCES +=  $$PWD/qscriptengine.cpp \
+            $$PWD/qscriptengine_p.cpp \
+            $$PWD/qscriptvalue.cpp \
+
+HEADERS +=  $$PWD/qtscriptglobal.h \
+            $$PWD/qscriptengine.h \
+            $$PWD/qscriptengine_p.h \
+            $$PWD/qscriptvalue.h \
+            $$PWD/qscriptvalue_p.h \
+            $$PWD/qscriptconverter_p.h \
+
+
+!static: DEFINES += QT_MAKEDLL
+
+DESTDIR = $$OUTPUT_DIR/lib
+
diff --git a/qt/api/qscriptconverter_p.h b/qt/api/qscriptconverter_p.h
new file mode 100644 (file)
index 0000000..c3ca41f
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+    Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptconverter_p_h
+#define qscriptconverter_p_h
+
+#include <JavaScriptCore/JavaScript.h>
+#include <QtCore/qstring.h>
+
+/*
+  \internal
+  \class QScriptConverter
+  QScriptValue and QScriptEngine helper class. This class's responsibility is to convert values
+  between JS values and Qt/C++ values.
+
+  This is a nice way to inline these functions in both QScriptValue and QScriptEngine.
+*/
+class QScriptConverter {
+public:
+    static QString toString(const JSStringRef str)
+    {
+        return QString(reinterpret_cast<const QChar*>(JSStringGetCharactersPtr(str)), JSStringGetLength(str));
+    }
+    static JSStringRef toString(const QString& str)
+    {
+        return JSStringCreateWithUTF8CString(str.toUtf8().constData());
+    }
+    static JSStringRef toString(const char* str)
+    {
+        return JSStringCreateWithUTF8CString(str);
+    }
+};
+
+#endif // qscriptconverter_p_h
diff --git a/qt/api/qscriptengine.cpp b/qt/api/qscriptengine.cpp
new file mode 100644 (file)
index 0000000..f12f410
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#include "qscriptengine.h"
+
+#include "qscriptengine_p.h"
+#include "qscriptvalue_p.h"
+
+/*!
+    Constructs a QScriptEngine object.
+
+    The globalObject() is initialized to have properties as described in ECMA-262, Section 15.1.
+*/
+QScriptEngine::QScriptEngine()
+    : d_ptr(new QScriptEnginePrivate(this))
+{
+}
+
+/*!
+    Destroys this QScriptEngine.
+*/
+QScriptEngine::~QScriptEngine()
+{
+}
+
+/*!
+    Evaluates \a program, using \a lineNumber as the base line number,
+    and returns the result of the evaluation.
+
+    The script code will be evaluated in the current context.
+
+    The evaluation of \a program can cause an exception in the
+    engine; in this case the return value will be the exception
+    that was thrown (typically an \c{Error} object). You can call
+    hasUncaughtException() to determine if an exception occurred in
+    the last call to evaluate().
+
+    \a lineNumber is used to specify a starting line number for \a
+    program; line number information reported by the engine that pertain
+    to this evaluation (e.g. uncaughtExceptionLineNumber()) will be
+    based on this argument. For example, if \a program consists of two
+    lines of code, and the statement on the second line causes a script
+    exception, uncaughtExceptionLineNumber() would return the given \a
+    lineNumber plus one. When no starting line number is specified, line
+    numbers will be 1-based.
+
+    \a fileName is used for error reporting. For example in error objects
+    the file name is accessible through the "fileName" property if it's
+    provided with this function.
+*/
+QScriptValue QScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
+{
+    return QScriptValuePrivate::get(d_ptr->evaluate(program, fileName, lineNumber));
+}
+
+/*!
+    Runs the garbage collector.
+
+    The garbage collector will attempt to reclaim memory by locating and disposing of objects that are
+    no longer reachable in the script environment.
+
+    Normally you don't need to call this function; the garbage collector will automatically be invoked
+    when the QScriptEngine decides that it's wise to do so (i.e. when a certain number of new objects
+    have been created). However, you can call this function to explicitly request that garbage
+    collection should be performed as soon as possible.
+*/
+void QScriptEngine::collectGarbage()
+{
+    d_ptr->collectGarbage();
+}
diff --git a/qt/api/qscriptengine.h b/qt/api/qscriptengine.h
new file mode 100644 (file)
index 0000000..cf61d35
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptengine_h
+#define qscriptengine_h
+
+#include <QtCore/qobject.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qstring.h>
+
+class QScriptValue;
+class QScriptEnginePrivate;
+
+// Internal typedef
+typedef QExplicitlySharedDataPointer<QScriptEnginePrivate> QScriptEnginePtr;
+
+class QScriptEngine : public QObject {
+public:
+    QScriptEngine();
+    ~QScriptEngine();
+
+    QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1);
+    void collectGarbage();
+
+private:
+    friend class QScriptEnginePrivate;
+
+    QScriptEnginePtr d_ptr;
+};
+
+#endif
diff --git a/qt/api/qscriptengine_p.cpp b/qt/api/qscriptengine_p.cpp
new file mode 100644 (file)
index 0000000..de8a355
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#include "qscriptengine_p.h"
+
+#include "qscriptvalue_p.h"
+
+/*!
+    Constructs a default QScriptEnginePrivate object, a new global context will be created.
+    \internal
+*/
+QScriptEnginePrivate::QScriptEnginePrivate(const QScriptEngine* engine)
+    : q_ptr(const_cast<QScriptEngine*>(engine))
+    , m_context(JSGlobalContextCreate(0))
+{
+}
+
+QScriptEnginePrivate::~QScriptEnginePrivate()
+{
+    JSGlobalContextRelease(m_context);
+}
+
+/*!
+    Evaluates program and returns the result of the evaluation.
+    \internal
+*/
+QScriptValuePrivate* QScriptEnginePrivate::evaluate(const QString& program, const QString& fileName, int lineNumber)
+{
+    JSStringRef script = QScriptConverter::toString(program);
+    JSStringRef file = QScriptConverter::toString(fileName);
+    JSValueRef exception;
+    JSValueRef result = JSEvaluateScript(m_context, script, /* Global Object */ 0, file, lineNumber, &exception);
+    if (!result)
+        return new QScriptValuePrivate(this, exception); // returns an exception
+    return new QScriptValuePrivate(this, result);
+}
diff --git a/qt/api/qscriptengine_p.h b/qt/api/qscriptengine_p.h
new file mode 100644 (file)
index 0000000..8e27c42
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptengine_p_h
+#define qscriptengine_p_h
+
+#include "qscriptconverter_p.h"
+#include "qscriptengine.h"
+#include "qscriptvalue.h"
+#include <JavaScriptCore/JavaScript.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qstring.h>
+
+class QScriptEngine;
+
+class QScriptEnginePrivate : public QSharedData {
+public:
+    static QScriptEnginePtr get(const QScriptEngine* q) { Q_ASSERT(q); return q->d_ptr; }
+    static QScriptEngine* get(const QScriptEnginePrivate* d) { Q_ASSERT(d); return d->q_ptr; }
+
+    QScriptEnginePrivate(const QScriptEngine*);
+    ~QScriptEnginePrivate();
+
+    QScriptValuePrivate* evaluate(const QString& program, const QString& fileName, int lineNumber);
+    inline void collectGarbage();
+
+    inline JSValueRef makeJSValue(double number) const;
+    inline JSValueRef makeJSValue(int number) const;
+    inline JSValueRef makeJSValue(uint number) const;
+    inline JSValueRef makeJSValue(const QString& string) const;
+    inline JSValueRef makeJSValue(bool number) const;
+    inline JSValueRef makeJSValue(QScriptValue::SpecialValue value) const;
+
+    inline JSGlobalContextRef context() const;
+private:
+    QScriptEngine* q_ptr;
+    JSGlobalContextRef m_context;
+};
+
+void QScriptEnginePrivate::collectGarbage()
+{
+    JSGarbageCollect(m_context);
+}
+
+JSValueRef QScriptEnginePrivate::makeJSValue(double number) const
+{
+    return JSValueMakeNumber(m_context, number);
+}
+
+JSValueRef QScriptEnginePrivate::makeJSValue(int number) const
+{
+    return JSValueMakeNumber(m_context, number);
+}
+
+JSValueRef QScriptEnginePrivate::makeJSValue(uint number) const
+{
+    return JSValueMakeNumber(m_context, number);
+}
+
+JSValueRef QScriptEnginePrivate::makeJSValue(const QString& string) const
+{
+    return JSValueMakeString(m_context, QScriptConverter::toString(string));
+}
+
+JSValueRef QScriptEnginePrivate::makeJSValue(bool value) const
+{
+    return JSValueMakeBoolean(m_context, value);
+}
+
+JSValueRef QScriptEnginePrivate::makeJSValue(QScriptValue::SpecialValue value) const
+{
+    if (value == QScriptValue::NullValue)
+        return JSValueMakeNull(m_context);
+    return JSValueMakeUndefined(m_context);
+}
+
+JSGlobalContextRef QScriptEnginePrivate::context() const
+{
+    return m_context;
+}
+
+#endif
diff --git a/qt/api/qscriptvalue.cpp b/qt/api/qscriptvalue.cpp
new file mode 100644 (file)
index 0000000..127fe04
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#include "qscriptvalue.h"
+
+#include "qscriptengine.h"
+#include "qscriptengine_p.h"
+#include "qscriptvalue_p.h"
+#include <QtCore/qdebug.h>
+
+/*!
+    Constructs an invalid value.
+*/
+QScriptValue::QScriptValue()
+    : d_ptr(new QScriptValuePrivate())
+{
+}
+
+/*!
+  Constructs a new QScriptValue with a boolean \a value.
+*/
+QScriptValue::QScriptValue(bool value)
+    : d_ptr(new QScriptValuePrivate(value))
+{
+}
+
+/*!
+  Constructs a new QScriptValue with a number \a value.
+*/
+QScriptValue::QScriptValue(int value)
+    : d_ptr(new QScriptValuePrivate(value))
+{
+}
+
+/*!
+  Constructs a new QScriptValue with a number \a value.
+*/
+QScriptValue::QScriptValue(uint value)
+    : d_ptr(new QScriptValuePrivate(value))
+{
+}
+
+/*!
+  Constructs a new QScriptValue with a number \a value.
+*/
+QScriptValue::QScriptValue(qsreal value)
+    : d_ptr(new QScriptValuePrivate(value))
+{
+}
+
+/*!
+  Constructs a new QScriptValue with a string \a value.
+*/
+QScriptValue::QScriptValue(const QString& value)
+    : d_ptr(new QScriptValuePrivate(value))
+{
+}
+
+/*!
+  Constructs a new QScriptValue with a special \a value.
+*/
+QScriptValue::QScriptValue(SpecialValue value)
+    : d_ptr(new QScriptValuePrivate(value))
+{
+}
+
+/*!
+  Constructs a new QScriptValue with a string \a value.
+*/
+QScriptValue::QScriptValue(const char* value)
+    : d_ptr(new QScriptValuePrivate(QString::fromUtf8(value)))
+{
+}
+
+/*!
+    Block automatic convertion to bool
+    \internal
+*/
+QScriptValue::QScriptValue(void* d)
+{
+    Q_ASSERT(false);
+}
+
+/*!
+    Constructs a new QScriptValue from private
+    \internal
+*/
+QScriptValue::QScriptValue(QScriptValuePrivate* d)
+    : d_ptr(d)
+{
+}
+
+/*!
+  \obsolete
+
+  Constructs a new QScriptValue with the boolean \a value and
+  registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine* engine, bool value)
+    : d_ptr(new QScriptValuePrivate(engine, value))
+{
+}
+
+/*!
+  \obsolete
+
+  Constructs a new QScriptValue with the integer \a value and
+  registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine* engine, int value)
+    : d_ptr(new QScriptValuePrivate(engine, value))
+{
+}
+
+/*!
+  \obsolete
+
+  Constructs a new QScriptValue with the unsigned integer \a value and
+  registers it with the script \a engine.
+ */
+QScriptValue::QScriptValue(QScriptEngine* engine, uint value)
+    : d_ptr(new QScriptValuePrivate(engine, value))
+{
+}
+
+/*!
+  \obsolete
+
+  Constructs a new QScriptValue with the qsreal \a value and
+  registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine* engine, qsreal value)
+    : d_ptr(new QScriptValuePrivate(engine, value))
+{
+}
+
+/*!
+  \obsolete
+
+  Constructs a new QScriptValue with the string \a value and
+  registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine* engine, const QString& value)
+    : d_ptr(new QScriptValuePrivate(engine, value))
+{
+}
+
+/*!
+  \obsolete
+
+  Constructs a new QScriptValue with the string \a value and
+  registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine* engine, const char* value)
+    : d_ptr(new QScriptValuePrivate(engine, QString::fromUtf8(value)))
+{
+}
+
+/*!
+  \obsolete
+
+  Constructs a new QScriptValue with the special \a value and
+  registers it with the script \a engine.
+*/
+QScriptValue::QScriptValue(QScriptEngine* engine, SpecialValue value)
+    : d_ptr(new QScriptValuePrivate(engine, value))
+{
+}
+
+/*!
+  Constructs a new QScriptValue that is a copy of \a other.
+
+  Note that if \a other is an object (i.e., isObject() would return
+  true), then only a reference to the underlying object is copied into
+  the new script value (i.e., the object itself is not copied).
+*/
+QScriptValue::QScriptValue(const QScriptValue& other)
+    : d_ptr(other.d_ptr)
+{
+}
+
+/*!
+    Destroys this QScriptValue.
+*/
+QScriptValue::~QScriptValue()
+{
+}
+
+/*!
+  Returns true if this QScriptValue is valid; otherwise returns
+  false.
+*/
+bool QScriptValue::isValid() const
+{
+    return d_ptr->isValid();
+}
+
+/*!
+  Returns true if this QScriptValue is of the primitive type Boolean;
+  otherwise returns false.
+
+  \sa toBool()
+*/
+bool QScriptValue::isBool() const
+{
+    return d_ptr->isBool();
+}
+
+/*!
+  \obsolete
+
+  Use isBool() instead.
+  Returns true if this QScriptValue is of the primitive type Boolean;
+  otherwise returns false.
+*/
+bool QScriptValue::isBoolean() const
+{
+    return d_ptr->isBool();
+}
+
+/*!
+  Returns true if this QScriptValue is of the primitive type Number;
+  otherwise returns false.
+
+  \sa toNumber()
+*/
+bool QScriptValue::isNumber() const
+{
+    return d_ptr->isNumber();
+}
+
+/*!
+  Returns true if this QScriptValue is of the primitive type Null;
+  otherwise returns false.
+
+  \sa QScriptEngine::nullValue()
+*/
+bool QScriptValue::isNull() const
+{
+    return d_ptr->isNull();
+}
+
+/*!
+  Returns true if this QScriptValue is of the primitive type String;
+  otherwise returns false.
+
+  \sa toString()
+*/
+bool QScriptValue::isString() const
+{
+    return d_ptr->isString();
+}
+
+/*!
+  Returns true if this QScriptValue is of the primitive type Undefined;
+  otherwise returns false.
+
+  \sa QScriptEngine::undefinedValue()
+*/
+bool QScriptValue::isUndefined() const
+{
+    return d_ptr->isUndefined();
+}
+
+/*!
+  Returns true if this QScriptValue is an object of the Error class;
+  otherwise returns false.
+
+  \sa QScriptContext::throwError()
+*/
+bool QScriptValue::isError() const
+{
+    return d_ptr->isError();
+}
+
+/*!
+  Returns true if this QScriptValue is of the Object type; otherwise
+  returns false.
+
+  Note that function values, variant values, and QObject values are
+  objects, so this function returns true for such values.
+
+  \sa toObject(), QScriptEngine::newObject()
+*/
+bool QScriptValue::isObject() const
+{
+    return d_ptr->isObject();
+}
+
+/*!
+  Returns true if this QScriptValue is a function; otherwise returns
+  false.
+
+  \sa call()
+*/
+bool QScriptValue::isFunction() const
+{
+    return d_ptr->isFunction();
+}
+
+/*!
+  Returns the string value of this QScriptValue, as defined in
+  \l{ECMA-262} section 9.8, "ToString".
+
+  Note that if this QScriptValue is an object, calling this function
+  has side effects on the script engine, since the engine will call
+  the object's toString() function (and possibly valueOf()) in an
+  attempt to convert the object to a primitive value (possibly
+  resulting in an uncaught script exception).
+
+  \sa isString()
+*/
+QString QScriptValue::toString() const
+{
+    return d_ptr->toString();
+}
+
+/*!
+  Returns the number value of this QScriptValue, as defined in
+  \l{ECMA-262} section 9.3, "ToNumber".
+
+  Note that if this QScriptValue is an object, calling this function
+  has side effects on the script engine, since the engine will call
+  the object's valueOf() function (and possibly toString()) in an
+  attempt to convert the object to a primitive value (possibly
+  resulting in an uncaught script exception).
+
+  \sa isNumber(), toInteger(), toInt32(), toUInt32(), toUInt16()
+*/
+qsreal QScriptValue::toNumber() const
+{
+    return d_ptr->toNumber();
+}
+
+/*!
+  Returns the boolean value of this QScriptValue, using the conversion
+  rules described in \l{ECMA-262} section 9.2, "ToBoolean".
+
+  Note that if this QScriptValue is an object, calling this function
+  has side effects on the script engine, since the engine will call
+  the object's valueOf() function (and possibly toString()) in an
+  attempt to convert the object to a primitive value (possibly
+  resulting in an uncaught script exception).
+
+  \sa isBool()
+*/
+bool QScriptValue::toBool() const
+{
+    return d_ptr->toBool();
+}
+
+/*!
+  \obsolete
+
+  Use toBool() instead.
+*/
+bool QScriptValue::toBoolean() const
+{
+    return d_ptr->toBool();
+}
+
+/*!
+  Returns the integer value of this QScriptValue, using the conversion
+  rules described in \l{ECMA-262} section 9.4, "ToInteger".
+
+  Note that if this QScriptValue is an object, calling this function
+  has side effects on the script engine, since the engine will call
+  the object's valueOf() function (and possibly toString()) in an
+  attempt to convert the object to a primitive value (possibly
+  resulting in an uncaught script exception).
+
+  \sa toNumber()
+*/
+qsreal QScriptValue::toInteger() const
+{
+    return d_ptr->toInteger();
+}
+
+/*!
+  Returns the signed 32-bit integer value of this QScriptValue, using
+  the conversion rules described in \l{ECMA-262} section 9.5, "ToInt32".
+
+  Note that if this QScriptValue is an object, calling this function
+  has side effects on the script engine, since the engine will call
+  the object's valueOf() function (and possibly toString()) in an
+  attempt to convert the object to a primitive value (possibly
+  resulting in an uncaught script exception).
+
+  \sa toNumber(), toUInt32()
+*/
+qint32 QScriptValue::toInt32() const
+{
+    return d_ptr->toInt32();
+}
+
+/*!
+  Returns the unsigned 32-bit integer value of this QScriptValue, using
+  the conversion rules described in \l{ECMA-262} section 9.6, "ToUint32".
+
+  Note that if this QScriptValue is an object, calling this function
+  has side effects on the script engine, since the engine will call
+  the object's valueOf() function (and possibly toString()) in an
+  attempt to convert the object to a primitive value (possibly
+  resulting in an uncaught script exception).
+
+  \sa toNumber(), toInt32()
+*/
+quint32 QScriptValue::toUInt32() const
+{
+    return d_ptr->toUInt32();
+}
+
+/*!
+  Returns the unsigned 16-bit integer value of this QScriptValue, using
+  the conversion rules described in \l{ECMA-262} section 9.7, "ToUint16".
+
+  Note that if this QScriptValue is an object, calling this function
+  has side effects on the script engine, since the engine will call
+  the object's valueOf() function (and possibly toString()) in an
+  attempt to convert the object to a primitive value (possibly
+  resulting in an uncaught script exception).
+
+  \sa toNumber()
+*/
+quint16 QScriptValue::toUInt16() const
+{
+    return d_ptr->toUInt16();
+}
+
+/*!
+  Calls this QScriptValue as a function, using \a thisObject as
+  the `this' object in the function call, and passing \a args
+  as arguments to the function. Returns the value returned from
+  the function.
+
+  If this QScriptValue is not a function, call() does nothing
+  and returns an invalid QScriptValue.
+
+  Note that if \a thisObject is not an object, the global object
+  (see \l{QScriptEngine::globalObject()}) will be used as the
+  `this' object.
+
+  Calling call() can cause an exception to occur in the script engine;
+  in that case, call() returns the value that was thrown (typically an
+  \c{Error} object). You can call
+  QScriptEngine::hasUncaughtException() to determine if an exception
+  occurred.
+
+  \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2
+
+  \sa construct()
+*/
+QScriptValue QScriptValue::call(const QScriptValue& thisObject, const QScriptValueList& args)
+{
+    return d_ptr->call(thisObject.d_ptr.data(), args);
+}
+
+/*!
+  Returns the QScriptEngine that created this QScriptValue,
+  or 0 if this QScriptValue is invalid or the value is not
+  associated with a particular engine.
+*/
+QScriptEngine* QScriptValue::engine() const
+{
+    QScriptEnginePrivate* engine = d_ptr->engine();
+    if (engine)
+        return QScriptEnginePrivate::get(engine);
+    return 0;
+}
+
+/*!
+  Assigns the \a other value to this QScriptValue.
+
+  Note that if \a other is an object (isObject() returns true),
+  only a reference to the underlying object will be assigned;
+  the object itself will not be copied.
+*/
+QScriptValue& QScriptValue::operator=(const QScriptValue& other)
+{
+    d_ptr = other.d_ptr;
+    return *this;
+}
+
+/*!
+  Returns true if this QScriptValue is equal to \a other, otherwise
+  returns false. The comparison follows the behavior described in
+  \l{ECMA-262} section 11.9.3, "The Abstract Equality Comparison
+  Algorithm".
+
+  This function can return true even if the type of this QScriptValue
+  is different from the type of the \a other value; i.e. the
+  comparison is not strict.  For example, comparing the number 9 to
+  the string "9" returns true; comparing an undefined value to a null
+  value returns true; comparing a \c{Number} object whose primitive
+  value is 6 to a \c{String} object whose primitive value is "6"
+  returns true; and comparing the number 1 to the boolean value
+  \c{true} returns true. If you want to perform a comparison
+  without such implicit value conversion, use strictlyEquals().
+
+  Note that if this QScriptValue or the \a other value are objects,
+  calling this function has side effects on the script engine, since
+  the engine will call the object's valueOf() function (and possibly
+  toString()) in an attempt to convert the object to a primitive value
+  (possibly resulting in an uncaught script exception).
+
+  \sa strictlyEquals(), lessThan()
+*/
+bool QScriptValue::equals(const QScriptValue& other) const
+{
+    return d_ptr == other.d_ptr || d_ptr->equals(QScriptValuePrivate::get(other));
+}
+
+/*!
+  Returns true if this QScriptValue is equal to \a other using strict
+  comparison (no conversion), otherwise returns false. The comparison
+  follows the behavior described in \l{ECMA-262} section 11.9.6, "The
+  Strict Equality Comparison Algorithm".
+
+  If the type of this QScriptValue is different from the type of the
+  \a other value, this function returns false. If the types are equal,
+  the result depends on the type, as shown in the following table:
+
+    \table
+    \header \o Type \o Result
+    \row    \o Undefined  \o true
+    \row    \o Null       \o true
+    \row    \o Boolean    \o true if both values are true, false otherwise
+    \row    \o Number     \o false if either value is NaN (Not-a-Number); true if values are equal, false otherwise
+    \row    \o String     \o true if both values are exactly the same sequence of characters, false otherwise
+    \row    \o Object     \o true if both values refer to the same object, false otherwise
+    \endtable
+
+  \sa equals()
+*/
+bool QScriptValue::strictlyEquals(const QScriptValue& other) const
+{
+    return d_ptr == other.d_ptr || d_ptr->strictlyEquals(QScriptValuePrivate::get(other));
+}
diff --git a/qt/api/qscriptvalue.h b/qt/api/qscriptvalue.h
new file mode 100644 (file)
index 0000000..d45aed3
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptvalue_h
+#define qscriptvalue_h
+
+#include <QtCore/qlist.h>
+#include <QtCore/qshareddata.h>
+
+class QScriptEngine;
+class QScriptValuePrivate;
+
+class QScriptValue;
+typedef QList<QScriptValue> QScriptValueList;
+
+typedef double qsreal;
+
+class QScriptValue {
+public:    
+    enum SpecialValue {
+        NullValue,
+        UndefinedValue
+    };
+
+    QScriptValue();
+    QScriptValue(bool value);
+    QScriptValue(int value);
+    QScriptValue(uint value);
+    QScriptValue(qsreal value);
+    QScriptValue(const QString& value);
+    QScriptValue(const char* value);
+    QScriptValue(SpecialValue value);
+    QScriptValue(const QScriptValue& other);
+
+    QScriptValue(QScriptEngine* engine, bool value);
+    QScriptValue(QScriptEngine* engine, int value);
+    QScriptValue(QScriptEngine* engine, uint value);
+    QScriptValue(QScriptEngine* engine, qsreal value);
+    QScriptValue(QScriptEngine* engine, const QString& value);
+    QScriptValue(QScriptEngine* engine, const char* value);
+    QScriptValue(QScriptEngine* engine, SpecialValue value);
+
+    ~QScriptValue();
+
+    QScriptValue& operator=(const QScriptValue& other);
+    bool equals(const QScriptValue& other) const;
+    bool strictlyEquals(const QScriptValue& other) const;
+
+    QScriptEngine* engine() const;
+
+    bool isValid() const;
+    bool isBool() const;
+    bool isBoolean() const;
+    bool isNumber() const;
+    bool isFunction() const;
+    bool isNull() const;
+    bool isString() const;
+    bool isUndefined() const;
+    bool isObject() const;
+    bool isError() const;
+
+    QString toString() const;
+    qsreal toNumber() const;
+    bool toBool() const;
+    bool toBoolean() const;
+    qsreal toInteger() const;
+    qint32 toInt32() const;
+    quint32 toUInt32() const;
+    quint16 toUInt16() const;
+
+    QScriptValue call(const QScriptValue& thisObject = QScriptValue(),
+                      const QScriptValueList& args = QScriptValueList());
+
+private:
+    QScriptValue(void*);
+    QScriptValue(QScriptValuePrivate*);
+
+    QExplicitlySharedDataPointer<QScriptValuePrivate> d_ptr;
+
+    friend class QScriptValuePrivate;
+};
+
+#endif // qscriptvalue_h
diff --git a/qt/api/qscriptvalue_p.h b/qt/api/qscriptvalue_p.h
new file mode 100644 (file)
index 0000000..6a5b388
--- /dev/null
@@ -0,0 +1,719 @@
+/*
+    Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptvalue_p_h
+#define qscriptvalue_p_h
+
+#include "qscriptconverter_p.h"
+#include "qscriptengine_p.h"
+#include "qscriptvalue.h"
+#include <JavaScriptCore/JavaScript.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qvarlengtharray.h>
+
+class QScriptEngine;
+class QScriptValue;
+
+/*
+  \internal
+  \class QScriptValuePrivate
+
+  Implementation of QScriptValue.
+  The implementation is based on a state machine. The states names are included in
+  QScriptValuePrivate::States. Each method should check for the current state and then perform a
+  correct action.
+
+  States:
+    Invalid -> QSVP is invalid, no assumptions should be made about class members (apart from m_value).
+    CString -> QSVP is created from QString or const char* and no JSC engine has been associated yet.
+        Current value is kept in m_string,
+    CNumber -> QSVP is created from int, uint, double... and no JSC engine has been bind yet. Current
+        value is kept in m_number
+    CBool -> QSVP is created from bool and no JSC engine has been associated yet. Current value is kept
+        in m_number
+    CSpecial -> QSVP is Undefined or Null, but a JSC engine hasn't been associated yet, current value
+        is kept in m_number (cast of QScriptValue::SpecialValue)
+    JSValue -> QSVP is associated with engine, but there is no information about real type, the state
+        have really short live cycle. Normally it is created as a function call result.
+    JSNative -> QSVP is associated with engine, and it is sure that it isn't a JavaScript object.
+    JSObject -> QSVP is associated with engine, and it is sure that it is a JavaScript object.
+
+  Each state keep all necessary information to invoke all methods, if not it should be changed to
+  a proper state. Changed state shouldn't be reverted.
+*/
+
+class QScriptValuePrivate : public QSharedData {
+public:
+    inline static QScriptValuePrivate* get(const QScriptValue& q);
+    inline static QScriptValue get(const QScriptValuePrivate* d);
+    inline static QScriptValue get(QScriptValuePrivate* d);
+
+    inline ~QScriptValuePrivate();
+
+    inline QScriptValuePrivate();
+    inline QScriptValuePrivate(const QString& string);
+    inline QScriptValuePrivate(bool value);
+    inline QScriptValuePrivate(int number);
+    inline QScriptValuePrivate(uint number);
+    inline QScriptValuePrivate(qsreal number);
+    inline QScriptValuePrivate(QScriptValue::SpecialValue value);
+
+    inline QScriptValuePrivate(const QScriptEngine* engine, bool value);
+    inline QScriptValuePrivate(const QScriptEngine* engine, int value);
+    inline QScriptValuePrivate(const QScriptEngine* engine, uint value);
+    inline QScriptValuePrivate(const QScriptEngine* engine, qsreal value);
+    inline QScriptValuePrivate(const QScriptEngine* engine, const QString& value);
+    inline QScriptValuePrivate(const QScriptEngine* engine, QScriptValue::SpecialValue value);
+
+    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value);
+    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object);
+
+    inline bool isValid() const;
+    inline bool isBool();
+    inline bool isNumber();
+    inline bool isNull();
+    inline bool isString();
+    inline bool isUndefined();
+    inline bool isError();
+    inline bool isObject();
+    inline bool isFunction();
+
+    inline QString toString() const;
+    inline qsreal toNumber() const;
+    inline bool toBool() const;
+    inline qsreal toInteger() const;
+    inline qint32 toInt32() const;
+    inline quint32 toUInt32() const;
+    inline quint16 toUInt16() const;
+
+    inline bool equals(QScriptValuePrivate* other);
+    inline bool strictlyEquals(const QScriptValuePrivate* other) const;
+    inline bool assignEngine(QScriptEnginePrivate* engine);
+
+    inline QScriptValuePrivate* call(const QScriptValuePrivate* , const QScriptValueList& args);
+
+    inline JSGlobalContextRef context() const;
+    inline JSValueRef value() const;
+    inline JSObjectRef object() const;
+    inline QScriptEnginePrivate* engine() const;
+
+private:
+    // Please, update class documentation when you change the enum.
+    enum States {
+        Invalid = 0,
+        CString = 0x1000,
+        CNumber,
+        CBool,
+        CSpecial,
+        JSValue = 0x2000, // JS values are equal or higher then this value.
+        JSNative,
+        JSObject
+    } m_state;
+    QScriptEnginePtr m_engine;
+    QString m_string;
+    qsreal m_number;
+    JSValueRef m_value;
+    JSObjectRef m_object;
+
+    inline void setValue(JSValueRef);
+
+    inline bool inherits(const char*);
+
+    inline bool isJSBased() const;
+    inline bool isNumberBased() const;
+    inline bool isStringBased() const;
+};
+
+QScriptValuePrivate* QScriptValuePrivate::get(const QScriptValue& q) { return q.d_ptr.data(); }
+
+QScriptValue QScriptValuePrivate::get(const QScriptValuePrivate* d)
+{
+    return QScriptValue(const_cast<QScriptValuePrivate*>(d));
+}
+
+QScriptValue QScriptValuePrivate::get(QScriptValuePrivate* d)
+{
+    return QScriptValue(d);
+}
+
+QScriptValuePrivate::~QScriptValuePrivate()
+{
+    if (m_value)
+        JSValueUnprotect(context(), m_value);
+}
+
+QScriptValuePrivate::QScriptValuePrivate()
+    : m_state(Invalid)
+    , m_value(0)
+{
+}
+
+QScriptValuePrivate::QScriptValuePrivate(const QString& string)
+    : m_state(CString)
+    , m_string(string)
+    , m_value(0)
+{
+}
+
+QScriptValuePrivate::QScriptValuePrivate(bool value)
+    : m_state(CBool)
+    , m_number(value)
+    , m_value(0)
+{
+}
+
+QScriptValuePrivate::QScriptValuePrivate(int number)
+    : m_state(CNumber)
+    , m_number(number)
+    , m_value(0)
+{
+}
+
+QScriptValuePrivate::QScriptValuePrivate(uint number)
+    : m_state(CNumber)
+    , m_number(number)
+    , m_value(0)
+{
+}
+
+QScriptValuePrivate::QScriptValuePrivate(qsreal number)
+    : m_state(CNumber)
+    , m_number(number)
+    , m_value(0)
+{
+}
+
+QScriptValuePrivate::QScriptValuePrivate(QScriptValue::SpecialValue value)
+    : m_state(CSpecial)
+    , m_number(value)
+    , m_value(0)
+{
+}
+
+QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, bool value)
+    : m_state(JSNative)
+{
+    if (!engine) {
+        // slower path reinitialization
+        m_state = CBool;
+        m_number = value;
+        m_value = 0;
+    } else {
+        m_engine = QScriptEnginePrivate::get(engine);
+        m_value = m_engine->makeJSValue(value);
+        JSValueProtect(context(), m_value);
+    }
+}
+
+QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, int value)
+    : m_state(JSNative)
+{
+    if (!engine) {
+        // slower path reinitialization
+        m_state = CNumber;
+        m_number = value;
+        m_value = 0;
+    } else {
+        m_engine = QScriptEnginePrivate::get(engine);
+        m_value = m_engine->makeJSValue(value);
+        JSValueProtect(context(), m_value);
+    }
+}
+
+QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, uint value)
+    : m_state(JSNative)
+{
+    if (!engine) {
+        // slower path reinitialization
+        m_state = CNumber;
+        m_number = value;
+        m_value = 0;
+    } else {
+        m_engine = QScriptEnginePrivate::get(engine);
+        m_value = m_engine->makeJSValue(value);
+        JSValueProtect(context(), m_value);
+    }
+}
+
+QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, qsreal value)
+    : m_state(JSNative)
+{
+    if (!engine) {
+        // slower path reinitialization
+        m_state = CNumber;
+        m_number = value;
+        m_value = 0;
+    } else {
+        m_engine = QScriptEnginePrivate::get(engine);
+        m_value = m_engine->makeJSValue(value);
+        JSValueProtect(context(), m_value);
+    }
+}
+
+QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, const QString& value)
+    : m_state(JSNative)
+{
+    if (!engine) {
+        // slower path reinitialization
+        m_state = CString;
+        m_string = value;
+        m_value = 0;
+    } else {
+        m_engine = QScriptEnginePrivate::get(engine);
+        m_value = m_engine->makeJSValue(value);
+        JSValueProtect(context(), m_value);
+    }
+}
+
+QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, QScriptValue::SpecialValue value)
+    : m_state(JSNative)
+{
+    if (!engine) {
+        // slower path reinitialization
+        m_state = CSpecial;
+        m_number = value;
+        m_value = 0;
+    } else {
+        m_engine = QScriptEnginePrivate::get(engine);
+        m_value = m_engine->makeJSValue(value);
+        JSValueProtect(context(), m_value);
+    }
+}
+
+QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value)
+    : m_state(JSValue)
+    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
+    , m_value(value)
+{
+    Q_ASSERT(engine);
+    JSValueProtect(context(), m_value);
+}
+
+QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object)
+    : m_state(JSObject)
+    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
+    , m_value(value)
+    , m_object(object)
+{
+    Q_ASSERT(engine);
+    JSValueProtect(context(), m_value);
+}
+
+bool QScriptValuePrivate::isValid() const { return m_state != Invalid; }
+
+bool QScriptValuePrivate::isBool()
+{
+    switch (m_state) {
+    case CBool:
+        return true;
+    case JSValue:
+        if (isObject())
+            return false;
+        // Fall-through.
+    case JSNative:
+        return JSValueIsBoolean(context(), value());
+    default:
+        return false;
+    }
+}
+
+bool QScriptValuePrivate::isNumber()
+{
+    switch (m_state) {
+    case CNumber:
+        return m_number;
+    case JSValue:
+        if (isObject())
+            return false;
+        // Fall-through.
+    case JSNative:
+        return JSValueIsNumber(context(), value());
+    default:
+        return false;
+    }
+}
+
+bool QScriptValuePrivate::isNull()
+{
+    switch (m_state) {
+    case CSpecial:
+        return m_number == static_cast<int>(QScriptValue::NullValue);
+    case JSValue:
+        if (isObject())
+            return false;
+        // Fall-through.
+    case JSNative:
+        return JSValueIsNull(context(), value());
+    default:
+        return false;
+    }
+}
+
+bool QScriptValuePrivate::isString()
+{
+    switch (m_state) {
+    case CString:
+        return true;
+    case JSValue:
+        if (isObject())
+            return false;
+        // Fall-through.
+    case JSNative:
+        return JSValueIsString(context(), value());
+    default:
+        return false;
+    }
+}
+
+bool QScriptValuePrivate::isUndefined()
+{
+    switch (m_state) {
+    case CSpecial:
+        return m_number == static_cast<int>(QScriptValue::UndefinedValue);
+    case JSValue:
+        if (isObject())
+            return false;
+        // Fall-through.
+    case JSNative:
+        return JSValueIsUndefined(context(), value());
+    default:
+        return false;
+    }
+}
+
+bool QScriptValuePrivate::isError()
+{
+    switch (m_state) {
+    case JSValue:
+        if (!isObject())
+            return false;
+        // Fall-through.
+    case JSObject:
+        return inherits("Error");
+    default:
+        return false;
+    }
+}
+
+bool QScriptValuePrivate::isObject()
+{
+    switch (m_state) {
+    case JSObject:
+        return true;
+    case JSValue:
+        m_object = JSValueToObject(context(), value(), /* exception */ 0);
+        if (!m_object)
+            return false;
+        m_state = JSObject;
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool QScriptValuePrivate::isFunction()
+{
+    switch (m_state) {
+    case JSValue:
+        m_object = JSValueToObject(context(), value(), /* exception */ 0);
+        if (!m_object)
+            return false;
+        m_state = JSObject;
+        // Fall-through.
+    case JSObject:
+        return JSObjectIsFunction(context(), object());
+    default:
+        return false;
+    }
+}
+
+QString QScriptValuePrivate::toString() const
+{
+    switch (m_state) {
+    case Invalid:
+        return QString();
+    case CBool:
+        return m_number ? QString::fromLatin1("true") : QString::fromLatin1("false");
+    case CString:
+        return m_string;
+    case CNumber:
+        return QString::number(m_number);
+    case CSpecial:
+        return m_number == QScriptValue::NullValue ? QString::fromLatin1("null") : QString::fromLatin1("undefined");
+    case JSValue:
+    case JSNative:
+    case JSObject:
+        return QScriptConverter::toString(JSValueToStringCopy(context(), value(), /* exception */ 0));
+    }
+
+    Q_ASSERT_X(false, "toString()", "Not all states are included in the previous switch statement.");
+    return QString(); // Avoid compiler warning.
+}
+
+qsreal QScriptValuePrivate::toNumber() const
+{
+    // TODO Check it.
+    switch (m_state) {
+    case JSValue:
+    case JSNative:
+    case JSObject:
+        return JSValueToNumber(context(), value(), /* exception */ 0);
+    case CNumber:
+    case CBool:
+        return m_number;
+    case Invalid:
+    case CSpecial:
+        return false;
+    case CString:
+        return m_string.isEmpty();
+    }
+
+    Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement.");
+    return 0; // Avoid compiler warning.
+}
+
+bool QScriptValuePrivate::toBool() const
+{
+    switch (m_state) {
+    case JSValue:
+    case JSNative:
+    case JSObject:
+        return JSValueToBoolean(context(), value());
+    case CNumber:
+    case CBool:
+        return m_number;
+    case Invalid:
+    case CSpecial:
+        return false;
+    case CString:
+        return m_string.isEmpty();
+    }
+
+    Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement.");
+    return false; // Avoid compiler warning.
+}
+
+qsreal QScriptValuePrivate::toInteger() const
+{
+    // TODO it is not true implementation!
+    return toNumber();
+}
+
+qint32 QScriptValuePrivate::toInt32() const
+{
+    // TODO it is not true implementation!
+    return toNumber();
+}
+
+quint32 QScriptValuePrivate::toUInt32() const
+{
+    // TODO it is not true implementation!
+    return toNumber();
+}
+
+quint16 QScriptValuePrivate::toUInt16() const
+{
+    // TODO it is not true implementation!
+    return toNumber();
+}
+
+
+bool QScriptValuePrivate::equals(QScriptValuePrivate* other)
+{
+    if (!isValid() || !other->isValid())
+        return false;
+
+    if ((m_state == other->m_state) && !isJSBased()) {
+        if (isNumberBased())
+            return m_number == other->m_number;
+        return m_string == other->m_string;
+    }
+
+    if (isJSBased() && !other->isJSBased()) {
+        if (!other->assignEngine(engine())) {
+            qWarning("equals(): Cannot compare to a value created in a different engine");
+            return false;
+        }
+    } else if (!isJSBased() && other->isJSBased()) {
+        if (!other->assignEngine(other->engine())) {
+            qWarning("equals(): Cannot compare to a value created in a different engine");
+            return false;
+        }
+    }
+
+    return JSValueIsEqual(context(), value(), other->value(), /* exception */ 0);
+}
+
+bool QScriptValuePrivate::strictlyEquals(const QScriptValuePrivate* other) const
+{
+    if (m_state != other->m_state)
+        return false;
+    if (isJSBased()) {
+        if (other->engine() != engine()) {
+            qWarning("strictlyEquals(): Cannot compare to a value created in a different engine");
+            return false;
+        }
+        return JSValueIsStrictEqual(context(), value(), other->value());
+    }
+    if (isStringBased())
+        return m_string == other->m_string;
+    if (isNumberBased())
+        return m_number == other->m_number;
+
+    return false; // Invalid state.
+}
+
+/*!
+  Tries to assign \a engine to this value. Returns true on success; otherwise returns false.
+*/
+bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
+{
+    JSValueRef value;
+    switch (m_state) {
+    case CBool:
+        value = engine->makeJSValue(static_cast<bool>(m_number));
+        break;
+    case CString:
+        value = engine->makeJSValue(m_string);
+        break;
+    case CNumber:
+        value = engine->makeJSValue(m_number);
+        break;
+    case CSpecial:
+        value = engine->makeJSValue(static_cast<QScriptValue::SpecialValue>(m_number));
+        break;
+    default:
+        if (!isJSBased())
+            Q_ASSERT_X(!isJSBased(), "assignEngine()", "Not all states are included in the previous switch statement.");
+        else
+            qWarning("JSValue can't be rassigned to an another engine.");
+        return false;
+    }
+    m_engine = engine;
+    m_state = JSNative;
+    setValue(value);
+    return true;
+}
+
+QScriptValuePrivate* QScriptValuePrivate::call(const QScriptValuePrivate*, const QScriptValueList& args)
+{
+    switch (m_state) {
+    case JSValue:
+        m_object = JSValueToObject(context(), value(), /* exception */ 0);
+        if (!object()) {
+            m_state = JSValue;
+            return new QScriptValuePrivate;
+        }
+        m_state = JSObject;
+        // Fall-through.
+    case JSObject:
+        {
+            // Convert all arguments and bind to the engine.
+            int argc = args.size();
+            QVarLengthArray<JSValueRef, 8> argv(argc);
+            QScriptValueList::const_iterator i = args.constBegin();
+            for (int j = 0; i != args.constEnd(); j++, i++) {
+                QScriptValuePrivate* value = QScriptValuePrivate::get(*i);
+                if (!value->assignEngine(engine())) {
+                    qWarning("QScriptValue::call() failed: cannot call function with values created in a different engine");
+                    return new QScriptValuePrivate;
+                }
+                argv[j] = value->value();
+            }
+
+            // Make the call
+            JSValueRef exception = 0;
+            JSValueRef result = JSObjectCallAsFunction(context(), object(), /* thisObject */ 0, argc, argv.constData(), &exception);
+            if (!result && exception)
+                return new QScriptValuePrivate(engine(), exception);
+            if (result && !exception)
+                return new QScriptValuePrivate(engine(), result);
+        }
+        // this QSV is not a function <-- !result && !exception. Fall-through.
+    default:
+        return new QScriptValuePrivate;
+    }
+}
+
+QScriptEnginePrivate* QScriptValuePrivate::engine() const
+{
+    // As long as m_engine is an autoinitializated pointer we can safely return it without
+    // checking current state.
+    return m_engine.data();
+}
+
+JSGlobalContextRef QScriptValuePrivate::context() const
+{
+    Q_ASSERT(isJSBased());
+    return m_engine->context();
+}
+
+JSValueRef QScriptValuePrivate::value() const
+{
+    Q_ASSERT(isJSBased());
+    return m_value;
+}
+
+JSObjectRef QScriptValuePrivate::object() const
+{
+    Q_ASSERT(m_state == JSObject);
+    return m_object;
+}
+
+void QScriptValuePrivate::setValue(JSValueRef value)
+{
+    if (m_value)
+        JSValueUnprotect(context(), m_value);
+    if (value)
+        JSValueProtect(context(), value);
+    m_value = value;
+}
+
+/*!
+  \internal
+  Returns true if QSV is created from constructor with the given \a name, it has to be a
+  built-in type.
+*/
+bool QScriptValuePrivate::inherits(const char* name)
+{
+    Q_ASSERT(isJSBased());
+    JSObjectRef globalObject = JSContextGetGlobalObject(context());
+    JSValueRef error = JSObjectGetProperty(context(), globalObject, QScriptConverter::toString(name), 0);
+    return JSValueIsInstanceOfConstructor(context(), value(), JSValueToObject(context(), error, /* exception */ 0), /* exception */ 0);
+}
+
+/*!
+  \internal
+  Returns true if QSV have an engine associated.
+*/
+bool QScriptValuePrivate::isJSBased() const { return m_state >= JSValue; }
+
+/*!
+  \internal
+  Returns true if current value of QSV is placed in m_number.
+*/
+bool QScriptValuePrivate::isNumberBased() const { return !isJSBased() && !isStringBased() && m_state != Invalid; }
+
+/*!
+  \internal
+  Returns true if current value of QSV is placed in m_string.
+*/
+bool QScriptValuePrivate::isStringBased() const { return m_state == CString; }
+
+#endif // qscriptvalue_p_h
diff --git a/qt/api/qtscriptglobal.h b/qt/api/qtscriptglobal.h
new file mode 100644 (file)
index 0000000..29749c0
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+    Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qtscriptglobal_h
+#define qtscriptglobal_h
+
+#include <QtCore/qglobal.h>
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+#  if defined(QT_NODLL)
+#  elif defined(QT_MAKEDLL)        /* create a Qt DLL library */
+#    if defined(QT_BUILD_JAVASCRIPT_LIB)
+#      define Q_JAVASCRIPT_EXPORT Q_DECL_EXPORT
+#    else
+#      define Q_JAVASCRIPT_EXPORT Q_DECL_IMPORT
+#    endif
+#  elif defined(QT_DLL) /* use a Qt DLL library */
+#    define Q_JAVASCRIPT_EXPORT
+#  endif
+#endif
+
+#if defined(QT_SHARED)
+#  define Q_JAVASCRIPT_EXPORT Q_DECL_EXPORT
+#else
+#  define Q_JAVASCRIPT_EXPORT
+#endif
+
+#endif
diff --git a/qt/tests/qscriptengine/qscriptengine.pro b/qt/tests/qscriptengine/qscriptengine.pro
new file mode 100644 (file)
index 0000000..0dc0902
--- /dev/null
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET = tst_qscriptengine
+QT += testlib
+include(../tests.pri)
+
+SOURCES += tst_qscriptengine.cpp
+
diff --git a/qt/tests/qscriptengine/tst_qscriptengine.cpp b/qt/tests/qscriptengine/tst_qscriptengine.cpp
new file mode 100644 (file)
index 0000000..37f3d11
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "qscriptengine.h"
+#include "qscriptvalue.h"
+#include <QtTest/qtest.h>
+
+class tst_QScriptEngine : public QObject {
+    Q_OBJECT
+
+public:
+    tst_QScriptEngine() {}
+    virtual ~tst_QScriptEngine() {}
+
+public slots:
+    void init() {}
+    void cleanup() {}
+
+private slots:
+    void evaluate();
+    void collectGarbage();
+};
+
+/* Evaluating a script that throw an unhandled exception should return an invalid value. */
+void tst_QScriptEngine::evaluate()
+{
+    QScriptEngine engine;
+    QVERIFY2(engine.evaluate("1+1").isValid(), "the expression should be evaluated and an valid result should be returned");
+    QVERIFY2(engine.evaluate("ping").isValid(), "Script throwing an unhandled exception should return an exception value");
+}
+
+/* Test garbage collection, at least try to not crash. */
+void tst_QScriptEngine::collectGarbage()
+{
+    QScriptEngine engine;
+    QScriptValue foo = engine.evaluate("( function foo() {return 'pong';} )");
+    QVERIFY(foo.isFunction());
+    engine.collectGarbage();
+    QCOMPARE(foo.call().toString(), QString::fromAscii("pong"));
+}
+QTEST_MAIN(tst_QScriptEngine)
+#include "tst_qscriptengine.moc"
diff --git a/qt/tests/qscriptvalue/qscriptvalue.pro b/qt/tests/qscriptvalue/qscriptvalue.pro
new file mode 100644 (file)
index 0000000..1ce5bc3
--- /dev/null
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET = tst_qscriptvalue
+QT += testlib
+include(../tests.pri)
+
+SOURCES += tst_qscriptvalue.cpp
+
diff --git a/qt/tests/qscriptvalue/tst_qscriptvalue.cpp b/qt/tests/qscriptvalue/tst_qscriptvalue.cpp
new file mode 100644 (file)
index 0000000..336a1a6
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "qscriptengine.h"
+#include "qscriptvalue.h"
+#include <QtTest/qtest.h>
+
+Q_DECLARE_METATYPE(QScriptValue*);
+Q_DECLARE_METATYPE(QScriptValue);
+
+class tst_QScriptValue : public QObject {
+    Q_OBJECT
+
+public:
+    tst_QScriptValue() {}
+    virtual ~tst_QScriptValue() {}
+
+private slots:
+    void toString_data();
+    void toString();
+    void copyConstructor_data();
+    void copyConstructor();
+    void assignOperator_data();
+    void assignOperator();
+    void dataSharing();
+    void constructors_data();
+    void constructors();
+    void call();
+
+    // copied from Qt's QtScript.
+    void ctor();
+};
+
+void tst_QScriptValue::ctor()
+{
+    QScriptEngine eng;
+    {
+        QScriptValue v;
+        QCOMPARE(v.isValid(), false);
+        QCOMPARE(v.engine(), (QScriptEngine *)0);
+    }
+    {
+        QScriptValue v(&eng, QScriptValue::UndefinedValue);
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isUndefined(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.engine(), &eng);
+    }
+    {
+        QScriptValue v(&eng, QScriptValue::NullValue);
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isNull(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.engine(), &eng);
+    }
+    {
+        QScriptValue v(&eng, false);
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isBoolean(), true);
+        QCOMPARE(v.isBool(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toBoolean(), false);
+        QCOMPARE(v.engine(), &eng);
+    }
+    {
+        QScriptValue v(&eng, int(1));
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isNumber(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toNumber(), 1.0);
+        QCOMPARE(v.engine(), &eng);
+    }
+    {
+        QScriptValue v(int(0x43211234));
+        QVERIFY(v.isNumber());
+        QCOMPARE(v.toInt32(), 0x43211234);
+    }
+    {
+        QScriptValue v(&eng, uint(1));
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isNumber(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toNumber(), 1.0);
+        QCOMPARE(v.engine(), &eng);
+    }
+    {
+        QScriptValue v(uint(0x43211234));
+        QVERIFY(v.isNumber());
+        QCOMPARE(v.toUInt32(), uint(0x43211234));
+    }
+    {
+        QScriptValue v(&eng, 1.0);
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isNumber(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toNumber(), 1.0);
+        QCOMPARE(v.engine(), &eng);
+    }
+    {
+        QScriptValue v(12345678910.5);
+        QVERIFY(v.isNumber());
+        QCOMPARE(v.toNumber(), 12345678910.5);
+    }
+    {
+        QScriptValue v(&eng, "ciao");
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isString(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toString(), QLatin1String("ciao"));
+        QCOMPARE(v.engine(), &eng);
+    }
+    {
+        QScriptValue v(&eng, QString("ciao"));
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isString(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toString(), QLatin1String("ciao"));
+        QCOMPARE(v.engine(), &eng);
+    }
+    // copy constructor, operator=
+    {
+        QScriptValue v(&eng, 1.0);
+        QScriptValue v2(v);
+        QCOMPARE(v2.strictlyEquals(v), true);
+        QCOMPARE(v2.engine(), &eng);
+
+        QScriptValue v3(v);
+        QCOMPARE(v3.strictlyEquals(v), true);
+        QCOMPARE(v3.strictlyEquals(v2), true);
+        QCOMPARE(v3.engine(), &eng);
+
+        QScriptValue v4(&eng, 2.0);
+        QCOMPARE(v4.strictlyEquals(v), false);
+        v3 = v4;
+        QCOMPARE(v3.strictlyEquals(v), false);
+        QCOMPARE(v3.strictlyEquals(v4), true);
+
+        v2 = QScriptValue();
+        QCOMPARE(v2.strictlyEquals(v), false);
+        QCOMPARE(v.toNumber(), 1.0);
+
+        QScriptValue v5(v);
+        QCOMPARE(v5.strictlyEquals(v), true);
+        v = QScriptValue();
+        QCOMPARE(v5.strictlyEquals(v), false);
+        QCOMPARE(v5.toNumber(), 1.0);
+    }
+
+    // constructors that take no engine argument
+    {
+        QScriptValue v(QScriptValue::UndefinedValue);
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isUndefined(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.engine(), (QScriptEngine *)0);
+    }
+    {
+        QScriptValue v(QScriptValue::NullValue);
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isNull(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.engine(), (QScriptEngine *)0);
+    }
+    {
+        QScriptValue v(false);
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isBoolean(), true);
+        QCOMPARE(v.isBool(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toBoolean(), false);
+        QCOMPARE(v.engine(), (QScriptEngine *)0);
+    }
+    {
+        QScriptValue v(int(1));
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isNumber(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toNumber(), 1.0);
+        QCOMPARE(v.engine(), (QScriptEngine *)0);
+    }
+    {
+        QScriptValue v(uint(1));
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isNumber(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toNumber(), 1.0);
+        QCOMPARE(v.engine(), (QScriptEngine *)0);
+    }
+    {
+        QScriptValue v(1.0);
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isNumber(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toNumber(), 1.0);
+        QCOMPARE(v.engine(), (QScriptEngine *)0);
+    }
+    {
+        QScriptValue v("ciao");
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isString(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toString(), QLatin1String("ciao"));
+        QCOMPARE(v.engine(), (QScriptEngine *)0);
+    }
+    {
+        QScriptValue v(QString("ciao"));
+        QCOMPARE(v.isValid(), true);
+        QCOMPARE(v.isString(), true);
+        QCOMPARE(v.isObject(), false);
+        QCOMPARE(v.toString(), QLatin1String("ciao"));
+        QCOMPARE(v.engine(), (QScriptEngine *)0);
+    }
+    // copy constructor, operator=
+    {
+        QScriptValue v(1.0);
+        QScriptValue v2(v);
+        QCOMPARE(v2.strictlyEquals(v), true);
+        QCOMPARE(v2.engine(), (QScriptEngine *)0);
+
+        QScriptValue v3(v);
+        QCOMPARE(v3.strictlyEquals(v), true);
+        QCOMPARE(v3.strictlyEquals(v2), true);
+        QCOMPARE(v3.engine(), (QScriptEngine *)0);
+
+        QScriptValue v4(2.0);
+        QCOMPARE(v4.strictlyEquals(v), false);
+        v3 = v4;
+        QCOMPARE(v3.strictlyEquals(v), false);
+        QCOMPARE(v3.strictlyEquals(v4), true);
+
+        v2 = QScriptValue();
+        QCOMPARE(v2.strictlyEquals(v), false);
+        QCOMPARE(v.toNumber(), 1.0);
+
+        QScriptValue v5(v);
+        QCOMPARE(v5.strictlyEquals(v), true);
+        v = QScriptValue();
+        QCOMPARE(v5.strictlyEquals(v), false);
+        QCOMPARE(v5.toNumber(), 1.0);
+    }
+
+    // 0 engine
+    QVERIFY(QScriptValue(0, QScriptValue::UndefinedValue).isUndefined());
+    QVERIFY(QScriptValue(0, QScriptValue::NullValue).isNull());
+    QVERIFY(QScriptValue(0, false).isBool());
+    QVERIFY(QScriptValue(0, int(1)).isNumber());
+    QVERIFY(QScriptValue(0, uint(1)).isNumber());
+    QVERIFY(QScriptValue(0, 1.0).isNumber());
+    QVERIFY(QScriptValue(0, "ciao").isString());
+    QVERIFY(QScriptValue(0, QString("ciao")).isString());
+}
+
+void tst_QScriptValue::toString_data()
+{
+    QTest::addColumn<QString>("code");
+    QTest::addColumn<QString>("result");
+
+    QTest::newRow("string") << QString::fromAscii("'hello'") << QString::fromAscii("hello");
+    QTest::newRow("string utf") << QString::fromUtf8("'ąśćżźółńę'") << QString::fromUtf8("ąśćżźółńę");
+    QTest::newRow("expression") << QString::fromAscii("1 + 4") << QString::fromAscii("5");
+    QTest::newRow("null") << QString::fromAscii("null") << QString::fromAscii("null");
+    QTest::newRow("boolean") << QString::fromAscii("false") << QString::fromAscii("false");
+    QTest::newRow("undefined") << QString::fromAscii("undefined") << QString::fromAscii("undefined");
+    QTest::newRow("object") << QString::fromAscii("new Object") << QString::fromAscii("[object Object]");
+}
+
+/* Test conversion to string from different JSC types */
+void tst_QScriptValue::toString()
+{
+    QFETCH(QString, code);
+    QFETCH(QString, result);
+
+    QScriptEngine engine;
+    QCOMPARE(engine.evaluate(code).toString(), result);
+}
+
+void tst_QScriptValue::copyConstructor_data()
+{
+    QScriptEngine engine;
+    QScriptValue nnumber(123);
+    QScriptValue nstring("ping");
+    QScriptValue number(engine.evaluate("1"));
+    QScriptValue string(engine.evaluate("'foo'"));
+    QScriptValue object(engine.evaluate("new Object"));
+    QScriptValue undefined(engine.evaluate("undefined"));
+    QScriptValue null(engine.evaluate("null"));
+
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<QString>("result");
+
+    QTest::newRow("native number") << nnumber << QString::number(123);
+    QTest::newRow("native string") << nstring << QString("ping");
+    QTest::newRow("number") << number << QString::fromAscii("1");
+    QTest::newRow("string") << string << QString::fromAscii("foo");
+    QTest::newRow("object") << object << QString::fromAscii("[object Object]");
+    QTest::newRow("undefined") << undefined << QString::fromAscii("undefined");
+    QTest::newRow("null") << null << QString::fromAscii("null");
+}
+
+void tst_QScriptValue::copyConstructor()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(QString, result);
+
+    QVERIFY(value.isValid());
+    QScriptValue tmp(value);
+    QVERIFY(tmp.isValid());
+    QCOMPARE(tmp.toString(), result);
+}
+
+void tst_QScriptValue::assignOperator_data()
+{
+    copyConstructor_data();
+}
+
+void tst_QScriptValue::assignOperator()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(QString, result);
+
+    QScriptValue tmp;
+    tmp = value;
+    QVERIFY(tmp.isValid());
+    QCOMPARE(tmp.toString(), result);
+}
+
+/* Test internal data sharing between a diffrenet QScriptValue. */
+void tst_QScriptValue::dataSharing()
+{
+    QScriptEngine engine;
+    QScriptValue v1;
+    QScriptValue v2(v1);
+
+    v1 = engine.evaluate("1"); // v1 == 1 ; v2 invalid.
+    QVERIFY(v1.isValid());
+    QVERIFY(!v2.isValid());
+
+    v2 = v1; // v1 == 1; v2 == 1.
+    QVERIFY(v1.isValid());
+    QVERIFY(v2.isValid());
+
+    v1 = engine.evaluate("obj = new Date"); // v1 == [object Date] ; v2 == 1.
+    QVERIFY(v1.isValid());
+    QVERIFY(v2.isValid());
+    QVERIFY(v2.toString() != v1.toString());
+
+    // TODO add object manipulation (v1 and v2 point to the same object).
+}
+
+void tst_QScriptValue::constructors_data()
+{
+    QScriptEngine engine;
+
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<QString>("string");
+    QTest::addColumn<bool>("valid");
+    QTest::addColumn<bool>("object");
+
+    QTest::newRow("invalid") << QScriptValue() << QString() << false << false;
+    QTest::newRow("number") << QScriptValue(-21) << QString::number(-21) << true << false;
+    QTest::newRow("bool") << QScriptValue(true) << QString::fromAscii("true") << true << false;
+    QTest::newRow("double") << QScriptValue(21.12) << QString::number(21.12) << true << false;
+    QTest::newRow("string") << QScriptValue("AlaMaKota") << QString::fromAscii("AlaMaKota") << true << false;
+    QTest::newRow("object") << engine.evaluate("new Object") << QString::fromAscii("[object Object]") << true << true;
+    QTest::newRow("null") << QScriptValue(QScriptValue::NullValue)<< QString::fromAscii("null") << true << false;
+    QTest::newRow("undef") << QScriptValue(QScriptValue::UndefinedValue)<< QString::fromAscii("undefined") << true << false;
+}
+
+void tst_QScriptValue::constructors()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(QString, string);
+    QFETCH(bool, valid);
+    QFETCH(bool, object);
+
+    QCOMPARE(value.isValid(), valid);
+    QCOMPARE(value.toString(), string);
+    QCOMPARE(value.isObject(), object);
+}
+
+void tst_QScriptValue::call()
+{
+    QScriptEngine engine;
+    QScriptValue ping = engine.evaluate("( function() {return 'ping';} )");
+    QScriptValue incr = engine.evaluate("( function(i) {return i + 1;} )");
+    QScriptValue one(1);
+    QScriptValue five(5);
+    QScriptValue result;
+
+    QVERIFY(one.isValid());
+    QVERIFY(five.isValid());
+
+    QVERIFY(ping.isValid());
+    QVERIFY(ping.isFunction());
+    result = ping.call();
+    QVERIFY(result.isValid());
+    QCOMPARE(result.toString(), QString::fromUtf8("ping"));
+
+    QVERIFY(incr.isValid());
+    QVERIFY(incr.isFunction());
+    result = incr.call(QScriptValue(), QScriptValueList() << one);
+    QVERIFY(result.isValid());
+    QCOMPARE(result.toString(), QString("2"));
+
+    QCOMPARE(incr.call(QScriptValue(), QScriptValueList() << five).toString(), QString::fromAscii("6"));
+
+    QVERIFY(incr.call().isValid()); // Exception.
+}
+
+QTEST_MAIN(tst_QScriptValue)
+#include "tst_qscriptvalue.moc"
diff --git a/qt/tests/tests.pri b/qt/tests/tests.pri
new file mode 100644 (file)
index 0000000..1ce238f
--- /dev/null
@@ -0,0 +1,28 @@
+isEmpty(OUTPUT_DIR) {
+    CONFIG(debug, debug|release) {
+        OUTPUT_DIR=$$PWD/WebKitBuild/Debug
+    } else { # Release
+        OUTPUT_DIR=$$PWD/WebKitBuild/Release
+    }
+}
+
+
+QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR
+QMAKE_LIBDIR = $$OUTPUT_DIR/lib $$QMAKE_LIBDIR
+mac:!static:contains(QT_CONFIG, qt_framework):!CONFIG(webkit_no_framework) {
+    LIBS += -framework QtScript
+    QMAKE_FRAMEWORKPATH = $$OUTPUT_DIR/lib $$QMAKE_FRAMEWORKPATH
+} else {
+    win32-*|wince* {
+        LIBS += -lQtScript$${QT_MAJOR_VERSION}
+    } else {
+        LIBS += -lQtScript
+    }
+}
+
+CONFIG(release, debug|release) {
+    DEFINES += NDEBUG
+}
+
+INCLUDEPATH += $$PWD/../api
+
diff --git a/qt/tests/tests.pro b/qt/tests/tests.pro
new file mode 100644 (file)
index 0000000..6e5edb1
--- /dev/null
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS =   qscriptengine \
+            qscriptvalue
index 0b5d958b6aaa35f61ec0517f50e20d57ea93cd53..ab2b5d7dae7143c5166aa943cb8abce37e4ba67e 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -37,16 +37,12 @@ void ArgList::getSlice(int startIndex, ArgList& result) const
     result = ArgList(m_args + startIndex, m_argCount - startIndex);
 }
 
     result = ArgList(m_args + startIndex, m_argCount - startIndex);
 }
 
-void MarkedArgumentBuffer::markLists(ListSet& markSet)
+void MarkedArgumentBuffer::markLists(MarkStack& markStack, ListSet& markSet)
 {
     ListSet::iterator end = markSet.end();
     for (ListSet::iterator it = markSet.begin(); it != end; ++it) {
         MarkedArgumentBuffer* list = *it;
 {
     ListSet::iterator end = markSet.end();
     for (ListSet::iterator it = markSet.begin(); it != end; ++it) {
         MarkedArgumentBuffer* list = *it;
-
-        iterator end2 = list->end();
-        for (iterator it2 = list->begin(); it2 != end2; ++it2)
-            if (!(*it2).marked())
-                (*it2).mark();
+        markStack.appendValues(reinterpret_cast<JSValue*>(list->m_buffer), list->m_size);
     }
 }
 
     }
 }
 
index 3c8256188e7fe6375a19463a03534549500f2684..8e1fdbe4b89af9084b631ae851c3304c1c45ad6c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007, 2008, 2009 Apple Computer, Inc.
+ *  Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 #define ArgList_h
 
 #include "Register.h"
 #define ArgList_h
 
 #include "Register.h"
-
 #include <wtf/HashSet.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
 #include <wtf/HashSet.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
-    
-    class MarkedArgumentBuffer : Noncopyable {
+
+    class MarkStack;
+
+    class MarkedArgumentBuffer : public Noncopyable {
     private:
         static const unsigned inlineCapacity = 8;
         typedef Vector<Register, inlineCapacity> VectorType;
     private:
         static const unsigned inlineCapacity = 8;
         typedef Vector<Register, inlineCapacity> VectorType;
@@ -103,7 +104,11 @@ namespace JSC {
         void append(JSValue v)
         {
             ASSERT(!m_isReadOnly);
         void append(JSValue v)
         {
             ASSERT(!m_isReadOnly);
-            
+
+#if ENABLE(JSC_ZOMBIES)
+            ASSERT(!v.isZombie());
+#endif
+
             if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
                 m_vector.uncheckedAppend(v);
                 ++m_size;
             if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
                 m_vector.uncheckedAppend(v);
                 ++m_size;
@@ -135,7 +140,7 @@ namespace JSC {
         const_iterator begin() const { return m_buffer; }
         const_iterator end() const { return m_buffer + m_size; }
 
         const_iterator begin() const { return m_buffer; }
         const_iterator end() const { return m_buffer + m_size; }
 
-        static void markLists(ListSet&);
+        static void markLists(MarkStack&, ListSet&);
 
     private:
         void slowAppend(JSValue);
 
     private:
         void slowAppend(JSValue);
@@ -186,6 +191,10 @@ namespace JSC {
             : m_args(args)
             , m_argCount(argCount)
         {
             : m_args(args)
             , m_argCount(argCount)
         {
+#if ENABLE(JSC_ZOMBIES)
+            for (size_t i = 0; i < argCount; i++)
+                ASSERT(!m_args[i].isZombie());
+#endif
         }
         
         ArgList(Register* args, int argCount)
         }
         
         ArgList(Register* args, int argCount)
index f867fe81f15fb5edcee66c404efbbe9d5896f724..bb30e3bc981b4740c8295f784cc5438402838a30 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -43,30 +43,22 @@ Arguments::~Arguments()
         delete [] d->extraArguments;
 }
 
         delete [] d->extraArguments;
 }
 
-void Arguments::mark()
+void Arguments::markChildren(MarkStack& markStack)
 {
 {
-    JSObject::mark();
+    JSObject::markChildren(markStack);
 
 
-    if (d->registerArray) {
-        for (unsigned i = 0; i < d->numParameters; ++i) {
-            if (!d->registerArray[i].marked())
-                d->registerArray[i].mark();
-        }
-    }
+    if (d->registerArray)
+        markStack.appendValues(reinterpret_cast<JSValue*>(d->registerArray.get()), d->numParameters);
 
     if (d->extraArguments) {
         unsigned numExtraArguments = d->numArguments - d->numParameters;
 
     if (d->extraArguments) {
         unsigned numExtraArguments = d->numArguments - d->numParameters;
-        for (unsigned i = 0; i < numExtraArguments; ++i) {
-            if (!d->extraArguments[i].marked())
-                d->extraArguments[i].mark();
-        }
+        markStack.appendValues(reinterpret_cast<JSValue*>(d->extraArguments), numExtraArguments);
     }
 
     }
 
-    if (!d->callee->marked())
-        d->callee->mark();
+    markStack.append(d->callee);
 
 
-    if (d->activation && !d->activation->marked())
-        d->activation->mark();
+    if (d->activation)
+        markStack.append(d->activation);
 }
 
 void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
 }
 
 void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
@@ -187,6 +179,44 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa
     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
+bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    bool isArrayIndex;
+    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
+        if (i < d->numParameters) {
+            descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].jsValue(), DontEnum);
+        } else
+            descriptor.setDescriptor(d->extraArguments[i - d->numParameters].jsValue(), DontEnum);
+        return true;
+    }
+    
+    if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
+        descriptor.setDescriptor(jsNumber(exec, d->numArguments), DontEnum);
+        return true;
+    }
+    
+    if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
+        descriptor.setDescriptor(d->callee, DontEnum);
+        return true;
+    }
+    
+    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
+void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    if (mode == IncludeDontEnumProperties) {
+        for (unsigned i = 0; i < d->numArguments; ++i) {
+            if (!d->deletedArguments || !d->deletedArguments[i])
+                propertyNames.add(Identifier(exec, UString::from(i)));
+        }
+        propertyNames.add(exec->propertyNames().callee);
+        propertyNames.add(exec->propertyNames().length);
+    }
+    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
 void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot)
 {
     if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
 void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot)
 {
     if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
index 74bb6ad8eede9223dabc0f10c0fe202d31c61d7b..9797e086d869ed9db628c735ac6d4f7f74f3deee 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -28,6 +28,8 @@
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "Interpreter.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "Interpreter.h"
+#include "ObjectConstructor.h"
+#include "PrototypeFunction.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -61,7 +63,7 @@ namespace JSC {
 
         static const ClassInfo info;
 
 
         static const ClassInfo info;
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
 
 
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
 
@@ -83,13 +85,18 @@ namespace JSC {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype) 
         { 
 
         static PassRefPtr<Structure> createStructure(JSValue prototype) 
         { 
-            return Structure::create(prototype, TypeInfo(ObjectType)); 
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
         }
 
         }
 
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
+
     private:
         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     private:
         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
@@ -113,8 +120,8 @@ namespace JSC {
     ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
     {
         function = callFrame->callee();
     ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
     {
         function = callFrame->callee();
-    
-        int numParameters = function->body()->parameterCount();
+
+        int numParameters = function->jsExecutable()->parameterCount();
         argc = callFrame->argumentCount();
 
         if (argc <= numParameters)
         argc = callFrame->argumentCount();
 
         if (argc <= numParameters)
@@ -136,7 +143,7 @@ namespace JSC {
         int numArguments;
         getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
 
         int numArguments;
         getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
 
-        d->numParameters = callee->body()->parameterCount();
+        d->numParameters = callee->jsExecutable()->parameterCount();
         d->firstParameterIndex = firstParameterIndex;
         d->numArguments = numArguments;
 
         d->firstParameterIndex = firstParameterIndex;
         d->numArguments = numArguments;
 
@@ -167,7 +174,7 @@ namespace JSC {
         : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
         , d(new ArgumentsData)
     {
         : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
         , d(new ArgumentsData)
     {
-        ASSERT(!callFrame->callee()->body()->parameterCount());
+        ASSERT(!callFrame->callee()->jsExecutable()->parameterCount());
 
         unsigned numArguments = callFrame->argumentCount() - 1;
 
 
         unsigned numArguments = callFrame->argumentCount() - 1;
 
@@ -213,8 +220,8 @@ namespace JSC {
     {
         ASSERT(!d()->registerArray);
 
     {
         ASSERT(!d()->registerArray);
 
-        size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
-        size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
+        size_t numParametersMinusThis = d()->functionExecutable->generatedBytecode().m_numParameters - 1;
+        size_t numVars = d()->functionExecutable->generatedBytecode().m_numVars;
         size_t numLocals = numVars + numParametersMinusThis;
 
         if (!numLocals)
         size_t numLocals = numVars + numParametersMinusThis;
 
         if (!numLocals)
index e96bdfc7bd2d9411d1e820ef2eb942f10a7d02ed..fb4449405130bd557d93cf576d57cb376b8d568a 100644 (file)
 #include "ArrayConstructor.h"
 
 #include "ArrayPrototype.h"
 #include "ArrayConstructor.h"
 
 #include "ArrayPrototype.h"
+#include "Error.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "Lookup.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "Lookup.h"
+#include "PrototypeFunction.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor);
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor);
+    
+static JSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*, JSObject*, JSValue, const ArgList&);
 
 
-ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype)
+ArrayConstructor::ArrayConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype, Structure* prototypeFunctionStructure)
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, arrayPrototype->classInfo()->className))
 {
     // ECMA 15.4.3.1 Array.prototype
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, arrayPrototype->classInfo()->className))
 {
     // ECMA 15.4.3.1 Array.prototype
@@ -41,9 +45,12 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> struct
 
     // no. of arguments for constructor
     putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
 
     // no. of arguments for constructor
     putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+
+    // ES5
+    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().isArray, arrayConstructorIsArray), DontEnum);
 }
 
 }
 
-static JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args)
+static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args)
 {
     // a single numeric argument denotes the array size (!)
     if (args.size() == 1 && args.at(0).isNumber()) {
 {
     // a single numeric argument denotes the array size (!)
     if (args.size() == 1 && args.at(0).isNumber()) {
@@ -82,4 +89,9 @@ CallType ArrayConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
     return CallTypeHost;
 }
 
+JSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*, JSObject*, JSValue, const ArgList& args)
+{
+    return jsBoolean(args.at(0).inherits(&JSArray::info));
+}
+
 } // namespace JSC
 } // namespace JSC
index 8300d8ce6525bc64568dd3ae3da4934ee1242116..6d25400145acfdec411427d699b46d404fbdf99f 100644 (file)
@@ -29,7 +29,7 @@ namespace JSC {
 
     class ArrayConstructor : public InternalFunction {
     public:
 
     class ArrayConstructor : public InternalFunction {
     public:
-        ArrayConstructor(ExecState*, PassRefPtr<Structure>, ArrayPrototype*);
+        ArrayConstructor(ExecState*, NonNullPassRefPtr<Structure>, ArrayPrototype*, Structure*);
 
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
 
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
index 807e59a67173732621ed21d7703f153ee4e16ecd..ce814b2adcca34f117e3777a29f70bd648ac9f1f 100644 (file)
@@ -67,7 +67,7 @@ static JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JS
 
 namespace JSC {
 
 
 namespace JSC {
 
-static inline bool isNumericCompareFunction(CallType callType, const CallData& callData)
+static inline bool isNumericCompareFunction(ExecState* exec, CallType callType, const CallData& callData)
 {
     if (callType != CallTypeJS)
         return false;
 {
     if (callType != CallTypeJS)
         return false;
@@ -75,10 +75,10 @@ static inline bool isNumericCompareFunction(CallType callType, const CallData& c
 #if ENABLE(JIT)
     // If the JIT is enabled then we need to preserve the invariant that every
     // function with a CodeBlock also has JIT code.
 #if ENABLE(JIT)
     // If the JIT is enabled then we need to preserve the invariant that every
     // function with a CodeBlock also has JIT code.
-    callData.js.functionBody->jitCode(callData.js.scopeChain);
-    CodeBlock& codeBlock = callData.js.functionBody->generatedBytecode();
+    callData.js.functionExecutable->jitCode(exec, callData.js.scopeChain);
+    CodeBlock& codeBlock = callData.js.functionExecutable->generatedBytecode();
 #else
 #else
-    CodeBlock& codeBlock = callData.js.functionBody->bytecode(callData.js.scopeChain);
+    CodeBlock& codeBlock = callData.js.functionExecutable->bytecode(exec, callData.js.scopeChain);
 #endif
 
     return codeBlock.isNumericCompareFunction();
 #endif
 
     return codeBlock.isNumericCompareFunction();
@@ -115,7 +115,7 @@ const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::a
 */
 
 // ECMA 15.4.4
 */
 
 // ECMA 15.4.4
-ArrayPrototype::ArrayPrototype(PassRefPtr<Structure> structure)
+ArrayPrototype::ArrayPrototype(NonNullPassRefPtr<Structure> structure)
     : JSArray(structure)
 {
 }
     : JSArray(structure)
 {
 }
@@ -125,6 +125,11 @@ bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& prope
     return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot);
 }
 
     return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot);
 }
 
+bool ArrayPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, descriptor);
+}
+
 // ------------------------------ Array Functions ----------------------------
 
 // Helper function
 // ------------------------------ Array Functions ----------------------------
 
 // Helper function
@@ -144,10 +149,11 @@ static void putProperty(ExecState* exec, JSObject* obj, const Identifier& proper
 
 JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 
 JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&JSArray::info))
+    bool isRealArray = isJSArray(&exec->globalData(), thisValue);
+    if (!isRealArray && !thisValue.inherits(&JSArray::info))
         return throwError(exec, TypeError);
         return throwError(exec, TypeError);
-    JSObject* thisObj = asArray(thisValue);
-
+    JSArray* thisObj = asArray(thisValue);
+    
     HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
     if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) {
         if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth)
     HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
     if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) {
         if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth)
@@ -158,39 +164,52 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue
     if (alreadyVisited)
         return jsEmptyString(exec); // return an empty string, avoiding infinite recursion.
 
     if (alreadyVisited)
         return jsEmptyString(exec); // return an empty string, avoiding infinite recursion.
 
-    Vector<UChar, 256> strBuffer;
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    unsigned totalSize = length ? length - 1 : 0;
+    Vector<RefPtr<UString::Rep>, 256> strBuffer(length);
     for (unsigned k = 0; k < length; k++) {
     for (unsigned k = 0; k < length; k++) {
-        if (k >= 1)
-            strBuffer.append(',');
-        if (!strBuffer.data()) {
-            JSObject* error = Error::create(exec, GeneralError, "Out of memory");
-            exec->setException(error);
-            break;
-        }
-
-        JSValue element = thisObj->get(exec, k);
+        JSValue element;
+        if (isRealArray && thisObj->canGetIndex(k))
+            element = thisObj->getIndex(k);
+        else
+            element = thisObj->get(exec, k);
+        
         if (element.isUndefinedOrNull())
             continue;
         if (element.isUndefinedOrNull())
             continue;
-
+        
         UString str = element.toString(exec);
         UString str = element.toString(exec);
-        strBuffer.append(str.data(), str.size());
-
+        strBuffer[k] = str.rep();
+        totalSize += str.size();
+        
         if (!strBuffer.data()) {
             JSObject* error = Error::create(exec, GeneralError, "Out of memory");
             exec->setException(error);
         }
         if (!strBuffer.data()) {
             JSObject* error = Error::create(exec, GeneralError, "Out of memory");
             exec->setException(error);
         }
-
+        
         if (exec->hadException())
             break;
     }
     arrayVisitedElements.remove(thisObj);
         if (exec->hadException())
             break;
     }
     arrayVisitedElements.remove(thisObj);
-    return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
+    if (!totalSize)
+        return jsEmptyString(exec);
+    Vector<UChar> buffer;
+    buffer.reserveCapacity(totalSize);
+    if (!buffer.data())
+        return throwError(exec, GeneralError, "Out of memory");
+        
+    for (unsigned i = 0; i < length; i++) {
+        if (i)
+            buffer.append(',');
+        if (RefPtr<UString::Rep> rep = strBuffer[i])
+            buffer.append(rep->data(), rep->size());
+    }
+    ASSERT(buffer.size() == totalSize);
+    return jsString(exec, UString::adopt(buffer));
 }
 
 JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&JSArray::info))
+    if (!thisValue.inherits(&JSArray::info))
         return throwError(exec, TypeError);
     JSObject* thisObj = asArray(thisValue);
 
         return throwError(exec, TypeError);
     JSObject* thisObj = asArray(thisValue);
 
@@ -298,7 +317,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue t
     ArgList::const_iterator it = args.begin();
     ArgList::const_iterator end = args.end();
     while (1) {
     ArgList::const_iterator it = args.begin();
     ArgList::const_iterator end = args.end();
     while (1) {
-        if (curArg.isObject(&JSArray::info)) {
+        if (curArg.inherits(&JSArray::info)) {
             unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec);
             JSObject* curObject = curArg.toObject(exec);
             for (unsigned k = 0; k < length; ++k) {
             unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec);
             JSObject* curObject = curArg.toObject(exec);
             for (unsigned k = 0; k < length; ++k) {
@@ -456,7 +475,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue thi
     CallType callType = function.getCallData(callData);
 
     if (thisObj->classInfo() == &JSArray::info) {
     CallType callType = function.getCallData(callData);
 
     if (thisObj->classInfo() == &JSArray::info) {
-        if (isNumericCompareFunction(callType, callData))
+        if (isNumericCompareFunction(exec, callType, callData))
             asArray(thisObj)->sortNumeric(exec, function, callType, callData);
         else if (callType != CallTypeNone)
             asArray(thisObj)->sort(exec, function, callType, callData);
             asArray(thisObj)->sortNumeric(exec, function, callType, callData);
         else if (callType != CallTypeNone)
             asArray(thisObj)->sort(exec, function, callType, callData);
@@ -725,8 +744,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue th
             cachedCall.setArgument(0, array->getIndex(k));
             cachedCall.setArgument(1, jsNumber(exec, k));
             cachedCall.setArgument(2, thisObj);
             cachedCall.setArgument(0, array->getIndex(k));
             cachedCall.setArgument(1, jsNumber(exec, k));
             cachedCall.setArgument(2, thisObj);
-            
-            if (!cachedCall.call().toBoolean(exec))
+            JSValue result = cachedCall.call();
+            if (!result.toBoolean(cachedCall.newCallFrame(exec)))
                 return jsBoolean(false);
         }
     }
                 return jsBoolean(false);
         }
     }
@@ -826,8 +845,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue thi
             cachedCall.setArgument(0, array->getIndex(k));
             cachedCall.setArgument(1, jsNumber(exec, k));
             cachedCall.setArgument(2, thisObj);
             cachedCall.setArgument(0, array->getIndex(k));
             cachedCall.setArgument(1, jsNumber(exec, k));
             cachedCall.setArgument(2, thisObj);
-            
-            if (cachedCall.call().toBoolean(exec))
+            JSValue result = cachedCall.call();
+            if (result.toBoolean(cachedCall.newCallFrame(exec)))
                 return jsBoolean(true);
         }
     }
                 return jsBoolean(true);
         }
     }
@@ -1014,7 +1033,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue
         JSValue e = getProperty(exec, thisObj, index);
         if (!e)
             continue;
         JSValue e = getProperty(exec, thisObj, index);
         if (!e)
             continue;
-        if (JSValue::strictEqual(searchElement, e))
+        if (JSValue::strictEqual(exec, searchElement, e))
             return jsNumber(exec, index);
     }
 
             return jsNumber(exec, index);
     }
 
@@ -1045,7 +1064,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSVa
         JSValue e = getProperty(exec, thisObj, index);
         if (!e)
             continue;
         JSValue e = getProperty(exec, thisObj, index);
         if (!e)
             continue;
-        if (JSValue::strictEqual(searchElement, e))
+        if (JSValue::strictEqual(exec, searchElement, e))
             return jsNumber(exec, index);
     }
 
             return jsNumber(exec, index);
     }
 
index 21650898e5de555a7aaa1b50cc061439e2fd0d65..e52914c2f2aa9132d5d7ef8b4fda318439016672 100644 (file)
@@ -28,9 +28,10 @@ namespace JSC {
 
     class ArrayPrototype : public JSArray {
     public:
 
     class ArrayPrototype : public JSArray {
     public:
-        explicit ArrayPrototype(PassRefPtr<Structure>);
+        explicit ArrayPrototype(NonNullPassRefPtr<Structure>);
 
         bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
 
         bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
index 8a954af1dbfafc4b01317635c35208868631a2bc..74089a53b9129c186839abb9625092c7215c7d99 100644 (file)
@@ -32,7 +32,7 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class BatchedTransitionOptimizer : Noncopyable {
+    class BatchedTransitionOptimizer : public Noncopyable {
     public:
         BatchedTransitionOptimizer(JSObject* object)
             : m_object(object)
     public:
         BatchedTransitionOptimizer(JSObject* object)
             : m_object(object)
index 9fcba374c06d0eb30676497ff52372227f6f6852..b0d8df38ea5dfecd9f0e04aa4ca498e3057e91b9 100644 (file)
@@ -28,7 +28,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
 
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
 
-BooleanConstructor::BooleanConstructor(ExecState* exec, PassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype)
+BooleanConstructor::BooleanConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype)
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, booleanPrototype->classInfo()->className))
 {
     putDirectWithoutTransition(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, booleanPrototype->classInfo()->className))
 {
     putDirectWithoutTransition(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
index d9f51ab52840e6665cccfac63d8a559517b608f0..1d8a26a57009b5bcaecd094ccd2bd31f4ab3acb5 100644 (file)
@@ -29,7 +29,7 @@ namespace JSC {
 
     class BooleanConstructor : public InternalFunction {
     public:
 
     class BooleanConstructor : public InternalFunction {
     public:
-        BooleanConstructor(ExecState*, PassRefPtr<Structure>, BooleanPrototype*);
+        BooleanConstructor(ExecState*, NonNullPassRefPtr<Structure>, BooleanPrototype*);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
index 01f695a8e30c4bf79a0c78bcdc4e2074a0327ab2..c9b3846597e68a1824f197577807a7772edad283 100644 (file)
@@ -27,7 +27,7 @@ ASSERT_CLASS_FITS_IN_CELL(BooleanObject);
 
 const ClassInfo BooleanObject::info = { "Boolean", 0, 0, 0 };
 
 
 const ClassInfo BooleanObject::info = { "Boolean", 0, 0, 0 };
 
-BooleanObject::BooleanObject(PassRefPtr<Structure> structure)
+BooleanObject::BooleanObject(NonNullPassRefPtr<Structure> structure)
     : JSWrapperObject(structure)
 {
 }
     : JSWrapperObject(structure)
 {
 }
index cfd55fe4da5c55746d528b164b36de09a1f31ed2..4b02acb1dc9503d9b0b77be650187eabb131c702 100644 (file)
@@ -27,10 +27,15 @@ namespace JSC {
 
     class BooleanObject : public JSWrapperObject {
     public:
 
     class BooleanObject : public JSWrapperObject {
     public:
-        explicit BooleanObject(PassRefPtr<Structure>);
+        explicit BooleanObject(NonNullPassRefPtr<Structure>);
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
+        
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+        }
     };
 
     BooleanObject* asBooleanObject(JSValue);
     };
 
     BooleanObject* asBooleanObject(JSValue);
index 703a56851dff81b5699e442ac6b6647b614b7372..8d338f9c3bf37eba25bbbfdae75d82699c0fe898 100644 (file)
@@ -37,7 +37,7 @@ static JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*, JSObject*, JSVa
 
 // ECMA 15.6.4
 
 
 // ECMA 15.6.4
 
-BooleanPrototype::BooleanPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+BooleanPrototype::BooleanPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
     : BooleanObject(structure)
 {
     setInternalValue(jsBoolean(false));
     : BooleanObject(structure)
 {
     setInternalValue(jsBoolean(false));
@@ -59,7 +59,7 @@ JSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec, JSObject*, JSVal
     if (thisValue == jsBoolean(true))
         return jsNontrivialString(exec, "true");
 
     if (thisValue == jsBoolean(true))
         return jsNontrivialString(exec, "true");
 
-    if (!thisValue.isObject(&BooleanObject::info))
+    if (!thisValue.inherits(&BooleanObject::info))
         return throwError(exec, TypeError);
 
     if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
         return throwError(exec, TypeError);
 
     if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
@@ -74,7 +74,7 @@ JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValu
     if (thisValue.isBoolean())
         return thisValue;
 
     if (thisValue.isBoolean())
         return thisValue;
 
-    if (!thisValue.isObject(&BooleanObject::info))
+    if (!thisValue.inherits(&BooleanObject::info))
         return throwError(exec, TypeError);
 
     return asBooleanObject(thisValue)->internalValue();
         return throwError(exec, TypeError);
 
     return asBooleanObject(thisValue)->internalValue();
index 16f80b52ec58fc35dbcd39a8eaa19d8f952a4cfe..cc69b3f00c699d99075232172c5a87914298d6de 100644 (file)
@@ -27,7 +27,7 @@ namespace JSC {
 
     class BooleanPrototype : public BooleanObject {
     public:
 
     class BooleanPrototype : public BooleanObject {
     public:
-        BooleanPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+        BooleanPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index d5b0172d8fdf804c44e30ab48e204cd5911628e7..24c19f91dbdf7f4c216ef71fe3a665f4a8d403d7 100644 (file)
@@ -35,7 +35,7 @@ namespace JSC {
 
     class ArgList;
     class ExecState;
 
     class ArgList;
     class ExecState;
-    class FunctionBodyNode;
+    class FunctionExecutable;
     class JSObject;
     class JSValue;
     class ScopeChainNode;
     class JSObject;
     class JSValue;
     class ScopeChainNode;
@@ -53,7 +53,7 @@ namespace JSC {
             NativeFunction function;
         } native;
         struct {
             NativeFunction function;
         } native;
         struct {
-            FunctionBodyNode* functionBody;
+            FunctionExecutable* functionExecutable;
             ScopeChainNode* scopeChain;
         } js;
     };
             ScopeChainNode* scopeChain;
         } js;
     };
index 097fb09962bd84668ce749a822d0cb81612e0fd8..acec4e78ddbf798607ca78a0098e03c7d3d84de2 100644 (file)
@@ -27,7 +27,7 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
-    struct HashEntry;
+    class HashEntry;
     struct HashTable;
 
     struct ClassInfo {
     struct HashTable;
 
     struct ClassInfo {
index 3d42bad860830858455bb719f23c2492c0dd8956..d252fb58180512669d206cd5c563aceea93992e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
  *
  *  This library is free software; you can redistribute it and/or
  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
  *
  *  This library is free software; you can redistribute it and/or
 
 #include "ArgList.h"
 #include "CallFrame.h"
 
 #include "ArgList.h"
 #include "CallFrame.h"
+#include "CodeBlock.h"
 #include "CollectorHeapIterator.h"
 #include "Interpreter.h"
 #include "CollectorHeapIterator.h"
 #include "Interpreter.h"
+#include "JSArray.h"
 #include "JSGlobalObject.h"
 #include "JSLock.h"
 #include "JSONObject.h"
 #include "JSString.h"
 #include "JSValue.h"
 #include "JSGlobalObject.h"
 #include "JSLock.h"
 #include "JSONObject.h"
 #include "JSString.h"
 #include "JSValue.h"
+#include "JSZombie.h"
+#include "MarkStack.h"
 #include "Nodes.h"
 #include "Tracing.h"
 #include <algorithm>
 #include "Nodes.h"
 #include "Tracing.h"
 #include <algorithm>
@@ -41,7 +45,7 @@
 #include <wtf/UnusedParam.h>
 #include <wtf/VMTags.h>
 
 #include <wtf/UnusedParam.h>
 #include <wtf/VMTags.h>
 
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 
 #include <mach/mach_init.h>
 #include <mach/mach_port.h>
 
 #include <mach/mach_init.h>
 #include <mach/mach_port.h>
 #include <mach/thread_act.h>
 #include <mach/vm_map.h>
 
 #include <mach/thread_act.h>
 #include <mach/vm_map.h>
 
-#elif PLATFORM(WIN_OS)
+#elif OS(SYMBIAN)
+#include <e32std.h>
+#include <e32cmn.h>
+#include <unistd.h>
+
+#elif OS(WINDOWS)
 
 #include <windows.h>
 
 #include <windows.h>
+#include <malloc.h>
+
+#elif OS(HAIKU)
 
 
-#elif PLATFORM(UNIX)
+#include <OS.h>
+
+#elif OS(UNIX)
 
 #include <stdlib.h>
 
 #include <stdlib.h>
+#if !OS(HAIKU)
 #include <sys/mman.h>
 #include <sys/mman.h>
+#endif
 #include <unistd.h>
 
 #include <unistd.h>
 
-#if PLATFORM(SOLARIS)
+#if OS(SOLARIS)
 #include <thread.h>
 #else
 #include <pthread.h>
 #include <thread.h>
 #else
 #include <pthread.h>
 #include <pthread_np.h>
 #endif
 
 #include <pthread_np.h>
 #endif
 
+#if OS(QNX)
+#include <fcntl.h>
+#include <sys/procfs.h>
+#include <stdio.h>
+#include <errno.h>
+#endif
+
 #endif
 
 #endif
 
-#define DEBUG_COLLECTOR 0
 #define COLLECT_ON_EVERY_ALLOCATION 0
 
 using std::max;
 #define COLLECT_ON_EVERY_ALLOCATION 0
 
 using std::max;
@@ -80,26 +102,24 @@ namespace JSC {
 
 // tunable parameters
 
 
 // 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 GROWTH_FACTOR = 2;
 const size_t LOW_WATER_FACTOR = 4;
-const size_t ALLOCATIONS_PER_COLLECTION = 4000;
+const size_t ALLOCATIONS_PER_COLLECTION = 3600;
 // This value has to be a macro to be used in max() without introducing
 // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
 #define MIN_ARRAY_SIZE (static_cast<size_t>(14))
 
 // 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 OS(SYMBIAN)
+const size_t MAX_NUM_BLOCKS = 256; // Max size of collector heap set to 16 MB
+static RHeap* userChunk = 0;
+#endif
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 typedef mach_port_t PlatformThread;
 typedef mach_port_t PlatformThread;
-#elif PLATFORM(WIN_OS)
-struct PlatformThread {
-    PlatformThread(DWORD _id, HANDLE _handle) : id(_id), handle(_handle) {}
-    DWORD id;
-    HANDLE handle;
-};
+#elif OS(WINDOWS)
+typedef HANDLE PlatformThread;
 #endif
 
 class Heap::Thread {
 #endif
 
 class Heap::Thread {
@@ -128,9 +148,29 @@ Heap::Heap(JSGlobalData* globalData)
     , m_globalData(globalData)
 {
     ASSERT(globalData);
     , m_globalData(globalData)
 {
     ASSERT(globalData);
-
-    memset(&primaryHeap, 0, sizeof(CollectorHeap));
-    memset(&numberHeap, 0, sizeof(CollectorHeap));
+    
+#if OS(SYMBIAN)
+    // Symbian OpenC supports mmap but currently not the MAP_ANON flag.
+    // Using fastMalloc() does not properly align blocks on 64k boundaries
+    // and previous implementation was flawed/incomplete.
+    // UserHeap::ChunkHeap allows allocation of continuous memory and specification
+    // of alignment value for (symbian) cells within that heap.
+    //
+    // Clarification and mapping of terminology:
+    // RHeap (created by UserHeap::ChunkHeap below) is continuos memory chunk,
+    // which can dynamically grow up to 8 MB,
+    // that holds all CollectorBlocks of this session (static).
+    // Each symbian cell within RHeap maps to a 64kb aligned CollectorBlock.
+    // JSCell objects are maintained as usual within CollectorBlocks.
+    if (!userChunk) {
+        userChunk = UserHeap::ChunkHeap(0, 0, MAX_NUM_BLOCKS * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
+        if (!userChunk)
+            CRASH();
+    }
+#endif // OS(SYMBIAN)
+    
+    memset(&m_heap, 0, sizeof(CollectorHeap));
+    allocateBlock();
 }
 
 Heap::~Heap()
 }
 
 Heap::~Heap()
@@ -141,11 +181,14 @@ Heap::~Heap()
 
 void Heap::destroy()
 {
 
 void Heap::destroy()
 {
-    JSLock lock(false);
+    JSLock lock(SilenceAssertionsOnly);
 
     if (!m_globalData)
         return;
 
 
     if (!m_globalData)
         return;
 
+    ASSERT(!m_globalData->dynamicGlobalObject);
+    ASSERT(!isBusy());
+    
     // The global object is not GC protected at this point, so sweeping may delete it
     // (and thus the global data) before other objects that may use the global data.
     RefPtr<JSGlobalData> protect(m_globalData);
     // 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);
@@ -153,13 +196,7 @@ void Heap::destroy()
     delete m_markListSet;
     m_markListSet = 0;
 
     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);
+    freeBlocks();
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
     if (m_currentThreadRegistrar) {
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
     if (m_currentThreadRegistrar) {
@@ -178,24 +215,29 @@ void Heap::destroy()
     m_globalData = 0;
 }
 
     m_globalData = 0;
 }
 
-template <HeapType heapType>
-static NEVER_INLINE CollectorBlock* allocateBlock()
+NEVER_INLINE CollectorBlock* Heap::allocateBlock()
 {
 {
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
     vm_address_t address = 0;
     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 | VM_TAG_FOR_COLLECTOR_MEMORY, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
     vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE | VM_TAG_FOR_COLLECTOR_MEMORY, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
-#elif PLATFORM(SYMBIAN)
-    // no memory map in symbian, need to hack with fastMalloc
-    void* address = fastMalloc(BLOCK_SIZE);
-    memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
-#elif PLATFORM(WIN_OS)
-     // windows virtual address granularity is naturally 64k
-    LPVOID address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+#elif OS(SYMBIAN)
+    // Allocate a 64 kb aligned CollectorBlock
+    unsigned char* mask = reinterpret_cast<unsigned char*>(userChunk->Alloc(BLOCK_SIZE));
+    if (!mask)
+        CRASH();
+    uintptr_t address = reinterpret_cast<uintptr_t>(mask);
+#elif OS(WINCE)
+    void* address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+#elif OS(WINDOWS)
+#if COMPILER(MINGW)
+    void* address = __mingw_aligned_malloc(BLOCK_SIZE, BLOCK_SIZE);
+#else
+    void* address = _aligned_malloc(BLOCK_SIZE, BLOCK_SIZE);
+#endif
+    memset(address, 0, BLOCK_SIZE);
 #elif HAVE(POSIX_MEMALIGN)
     void* address;
     posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE);
 #elif HAVE(POSIX_MEMALIGN)
     void* address;
     posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE);
-    memset(address, 0, BLOCK_SIZE);
 #else
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 #else
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
@@ -221,20 +263,68 @@ static NEVER_INLINE CollectorBlock* allocateBlock()
         munmap(reinterpret_cast<char*>(address + adjust + BLOCK_SIZE), extra - adjust);
 
     address += adjust;
         munmap(reinterpret_cast<char*>(address + adjust + BLOCK_SIZE), extra - adjust);
 
     address += adjust;
-    memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
 #endif
 #endif
-    reinterpret_cast<CollectorBlock*>(address)->type = heapType;
-    return reinterpret_cast<CollectorBlock*>(address);
+
+    // Initialize block.
+
+    CollectorBlock* block = reinterpret_cast<CollectorBlock*>(address);
+    block->heap = this;
+    clearMarkBits(block);
+
+    Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get();
+    for (size_t i = 0; i < HeapConstants::cellsPerBlock; ++i)
+        new (block->cells + i) JSCell(dummyMarkableCellStructure);
+    
+    // Add block to blocks vector.
+
+    size_t numBlocks = m_heap.numBlocks;
+    if (m_heap.usedBlocks == numBlocks) {
+        static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR;
+        if (numBlocks > maxNumBlocks)
+            CRASH();
+        numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
+        m_heap.numBlocks = numBlocks;
+        m_heap.blocks = static_cast<CollectorBlock**>(fastRealloc(m_heap.blocks, numBlocks * sizeof(CollectorBlock*)));
+    }
+    m_heap.blocks[m_heap.usedBlocks++] = block;
+
+    return block;
+}
+
+NEVER_INLINE void Heap::freeBlock(size_t block)
+{
+    m_heap.didShrink = true;
+
+    ObjectIterator it(m_heap, block);
+    ObjectIterator end(m_heap, block + 1);
+    for ( ; it != end; ++it)
+        (*it)->~JSCell();
+    freeBlockPtr(m_heap.blocks[block]);
+
+    // swap with the last block so we compact as we go
+    m_heap.blocks[block] = m_heap.blocks[m_heap.usedBlocks - 1];
+    m_heap.usedBlocks--;
+
+    if (m_heap.numBlocks > MIN_ARRAY_SIZE && m_heap.usedBlocks < m_heap.numBlocks / LOW_WATER_FACTOR) {
+        m_heap.numBlocks = m_heap.numBlocks / GROWTH_FACTOR; 
+        m_heap.blocks = static_cast<CollectorBlock**>(fastRealloc(m_heap.blocks, m_heap.numBlocks * sizeof(CollectorBlock*)));
+    }
 }
 
 }
 
-static void freeBlock(CollectorBlock* block)
+NEVER_INLINE void Heap::freeBlockPtr(CollectorBlock* block)
 {
 {
-#if PLATFORM(DARWIN)    
+#if OS(DARWIN)    
     vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE);
     vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE);
-#elif PLATFORM(SYMBIAN)
-    fastFree(block);
-#elif PLATFORM(WIN_OS)
+#elif OS(SYMBIAN)
+    userChunk->Free(reinterpret_cast<TAny*>(block));
+#elif OS(WINCE)
     VirtualFree(block, 0, MEM_RELEASE);
     VirtualFree(block, 0, MEM_RELEASE);
+#elif OS(WINDOWS)
+#if COMPILER(MINGW)
+    __mingw_aligned_free(block);
+#else
+    _aligned_free(block);
+#endif
 #elif HAVE(POSIX_MEMALIGN)
     free(block);
 #else
 #elif HAVE(POSIX_MEMALIGN)
     free(block);
 #else
@@ -242,13 +332,34 @@ static void freeBlock(CollectorBlock* block)
 #endif
 }
 
 #endif
 }
 
-static void freeHeap(CollectorHeap* heap)
+void Heap::freeBlocks()
 {
 {
-    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));
+    ProtectCountSet protectedValuesCopy = m_protectedValues;
+
+    clearMarkBits();
+    ProtectCountSet::iterator protectedValuesEnd = protectedValuesCopy.end();
+    for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it)
+        markCell(it->first);
+
+    m_heap.nextCell = 0;
+    m_heap.nextBlock = 0;
+    DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell);
+    DeadObjectIterator end(m_heap, m_heap.usedBlocks);
+    for ( ; it != end; ++it)
+        (*it)->~JSCell();
+
+    ASSERT(!protectedObjectCount());
+
+    protectedValuesEnd = protectedValuesCopy.end();
+    for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it)
+        it->first->~JSCell();
+
+    for (size_t block = 0; block < m_heap.usedBlocks; ++block)
+        freeBlockPtr(m_heap.blocks[block]);
+
+    fastFree(m_heap.blocks);
+
+    memset(&m_heap, 0, sizeof(CollectorHeap));
 }
 
 void Heap::recordExtraCost(size_t cost)
 }
 
 void Heap::recordExtraCost(size_t cost)
@@ -263,138 +374,109 @@ void Heap::recordExtraCost(size_t cost)
     // 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.
     // 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;
+    if (m_heap.extraCost > maxExtraCost && m_heap.extraCost > m_heap.usedBlocks * BLOCK_SIZE / 2) {
+        // If the last iteration through the heap deallocated blocks, we need
+        // to clean up remaining garbage before marking. Otherwise, the conservative
+        // marking mechanism might follow a pointer to unmapped memory.
+        if (m_heap.didShrink)
+            sweep();
+        reset();
+    }
+    m_heap.extraCost += cost;
 }
 
 }
 
-template <HeapType heapType> ALWAYS_INLINE void* Heap::heapAllocate(size_t s)
+void* Heap::allocate(size_t s)
 {
 {
-    typedef typename HeapConstants<heapType>::Block Block;
-    typedef typename HeapConstants<heapType>::Cell Cell;
-
-    CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
+    typedef HeapConstants::Block Block;
+    typedef HeapConstants::Cell Cell;
+    
     ASSERT(JSLock::lockCount() > 0);
     ASSERT(JSLock::currentThreadIsHoldingLock());
     ASSERT(JSLock::lockCount() > 0);
     ASSERT(JSLock::currentThreadIsHoldingLock());
-    ASSERT_UNUSED(s, s <= HeapConstants<heapType>::cellSize);
+    ASSERT_UNUSED(s, s <= HeapConstants::cellSize);
 
 
-    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 CRASH() in NDEBUG builds, which could help ensure we
-    // don't spend any time debugging cases where we allocate inside an object's
-    // deallocation code.
+    ASSERT(m_heap.operationInProgress == NoOperation);
 
 #if COLLECT_ON_EVERY_ALLOCATION
 
 #if COLLECT_ON_EVERY_ALLOCATION
-    collect();
+    collectAllGarbage();
+    ASSERT(m_heap.operationInProgress == NoOperation);
 #endif
 
 #endif
 
-    size_t numLiveObjects = heap.numLiveObjects;
-    size_t usedBlocks = heap.usedBlocks;
-    size_t i = heap.firstBlockWithPossibleSpace;
-
-    // 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;
-    }
+allocate:
 
 
-    ASSERT(heap.operationInProgress == NoOperation);
-#ifndef NDEBUG
-    // FIXME: Consider doing this in NDEBUG builds too (see comment above).
-    heap.operationInProgress = Allocation;
-#endif
+    // Fast case: find the next garbage cell and recycle it.
 
 
-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 {
+    do {
+        ASSERT(m_heap.nextBlock < m_heap.usedBlocks);
+        Block* block = reinterpret_cast<Block*>(m_heap.blocks[m_heap.nextBlock]);
+        do {
+            ASSERT(m_heap.nextCell < HeapConstants::cellsPerBlock);
+            if (!block->marked.get(m_heap.nextCell)) { // Always false for the last cell in the block
+                Cell* cell = block->cells + m_heap.nextCell;
 
 
-collect:
-        size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
-        size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
-        const size_t newCost = numNewObjects + heap.extraCost;
+                m_heap.operationInProgress = Allocation;
+                JSCell* imp = reinterpret_cast<JSCell*>(cell);
+                imp->~JSCell();
+                m_heap.operationInProgress = NoOperation;
 
 
-        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;
+                ++m_heap.nextCell;
+                return cell;
             }
             }
-        }
-  
-        // 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) {
-            static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR;
-            if (numBlocks > maxNumBlocks)
-                CRASH();
-            numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
-            heap.numBlocks = numBlocks;
-            heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*)));
-        }
+        } while (++m_heap.nextCell != HeapConstants::cellsPerBlock);
+        m_heap.nextCell = 0;
+    } while (++m_heap.nextBlock != m_heap.usedBlocks);
 
 
-        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;
+    // Slow case: reached the end of the heap. Mark live objects and start over.
 
 
-    // "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;
+    reset();
+    goto allocate;
+}
 
 
-    targetBlock->usedCells = static_cast<uint32_t>(targetBlockUsedCells + 1);
-    heap.numLiveObjects = numLiveObjects + 1;
+void Heap::resizeBlocks()
+{
+    m_heap.didShrink = false;
 
 
-#ifndef NDEBUG
-    // FIXME: Consider doing this in NDEBUG builds too (see comment above).
-    heap.operationInProgress = NoOperation;
-#endif
+    size_t usedCellCount = markedCells();
+    size_t minCellCount = usedCellCount + max(ALLOCATIONS_PER_COLLECTION, usedCellCount);
+    size_t minBlockCount = (minCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock;
+
+    size_t maxCellCount = 1.25f * minCellCount;
+    size_t maxBlockCount = (maxCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock;
 
 
-    return newCell;
+    if (m_heap.usedBlocks < minBlockCount)
+        growBlocks(minBlockCount);
+    else if (m_heap.usedBlocks > maxBlockCount)
+        shrinkBlocks(maxBlockCount);
 }
 
 }
 
-void* Heap::allocate(size_t s)
+void Heap::growBlocks(size_t neededBlocks)
 {
 {
-    return heapAllocate<PrimaryHeap>(s);
+    ASSERT(m_heap.usedBlocks < neededBlocks);
+    while (m_heap.usedBlocks < neededBlocks)
+        allocateBlock();
 }
 
 }
 
-void* Heap::allocateNumber(size_t s)
+void Heap::shrinkBlocks(size_t neededBlocks)
 {
 {
-    return heapAllocate<NumberHeap>(s);
+    ASSERT(m_heap.usedBlocks > neededBlocks);
+    
+    // Clear the always-on last bit, so isEmpty() isn't fooled by it.
+    for (size_t i = 0; i < m_heap.usedBlocks; ++i)
+        m_heap.blocks[i]->marked.clear(HeapConstants::cellsPerBlock - 1);
+
+    for (size_t i = 0; i != m_heap.usedBlocks && m_heap.usedBlocks != neededBlocks; ) {
+        if (m_heap.blocks[i]->marked.isEmpty()) {
+            freeBlock(i);
+        } else
+            ++i;
+    }
+
+    // Reset the always-on last bit.
+    for (size_t i = 0; i < m_heap.usedBlocks; ++i)
+        m_heap.blocks[i]->marked.set(HeapConstants::cellsPerBlock - 1);
 }
 
 }
 
-#if PLATFORM(WINCE)
+#if OS(WINCE)
 void* g_stackBase = 0;
 
 inline bool isPageWritable(void* page)
 void* g_stackBase = 0;
 
 inline bool isPageWritable(void* page)
@@ -451,12 +533,39 @@ static void* getStackBase(void* previousFrame)
 }
 #endif
 
 }
 #endif
 
+#if OS(QNX)
+static inline void *currentThreadStackBaseQNX()
+{
+    static void* stackBase = 0;
+    static size_t stackSize = 0;
+    static pthread_t stackThread;
+    pthread_t thread = pthread_self();
+    if (stackBase == 0 || thread != stackThread) {
+        struct _debug_thread_info threadInfo;
+        memset(&threadInfo, 0, sizeof(threadInfo));
+        threadInfo.tid = pthread_self();
+        int fd = open("/proc/self", O_RDONLY);
+        if (fd == -1) {
+            LOG_ERROR("Unable to open /proc/self (errno: %d)", errno);
+            return 0;
+        }
+        devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0);
+        close(fd);
+        stackBase = reinterpret_cast<void*>(threadInfo.stkbase);
+        stackSize = threadInfo.stksize;
+        ASSERT(stackBase);
+        stackThread = thread;
+    }
+    return static_cast<char*>(stackBase) + stackSize;
+}
+#endif
+
 static inline void* currentThreadStackBase()
 {
 static inline void* currentThreadStackBase()
 {
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
     pthread_t thread = pthread_self();
     return pthread_get_stackaddr_np(thread);
     pthread_t thread = pthread_self();
     return pthread_get_stackaddr_np(thread);
-#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(MSVC)
+#elif OS(WINDOWS) && CPU(X86) && COMPILER(MSVC)
     // offset 0x18 from the FS segment register gives a pointer to
     // the thread information block for the current thread
     NT_TIB* pTib;
     // offset 0x18 from the FS segment register gives a pointer to
     // the thread information block for the current thread
     NT_TIB* pTib;
@@ -465,10 +574,11 @@ static inline void* currentThreadStackBase()
         MOV pTib, EAX
     }
     return static_cast<void*>(pTib->StackBase);
         MOV pTib, EAX
     }
     return static_cast<void*>(pTib->StackBase);
-#elif PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC)
+#elif OS(WINDOWS) && CPU(X86_64) && COMPILER(MSVC)
+    // FIXME: why only for MSVC?
     PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
     return reinterpret_cast<void*>(pTib->StackBase);
     PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
     return reinterpret_cast<void*>(pTib->StackBase);
-#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(GCC)
+#elif OS(WINDOWS) && CPU(X86) && COMPILER(GCC)
     // offset 0x18 from the FS segment register gives a pointer to
     // the thread information block for the current thread
     NT_TIB* pTib;
     // offset 0x18 from the FS segment register gives a pointer to
     // the thread information block for the current thread
     NT_TIB* pTib;
@@ -476,16 +586,18 @@ static inline void* currentThreadStackBase()
           : "=r" (pTib)
         );
     return static_cast<void*>(pTib->StackBase);
           : "=r" (pTib)
         );
     return static_cast<void*>(pTib->StackBase);
-#elif PLATFORM(SOLARIS)
+#elif OS(QNX)
+    return currentThreadStackBaseQNX();
+#elif OS(SOLARIS)
     stack_t s;
     thr_stksegment(&s);
     return s.ss_sp;
     stack_t s;
     thr_stksegment(&s);
     return s.ss_sp;
-#elif PLATFORM(OPENBSD)
+#elif OS(OPENBSD)
     pthread_t thread = pthread_self();
     stack_t stack;
     pthread_stackseg_np(thread, &stack);
     return stack.ss_sp;
     pthread_t thread = pthread_self();
     stack_t stack;
     pthread_stackseg_np(thread, &stack);
     return stack.ss_sp;
-#elif PLATFORM(SYMBIAN)
+#elif OS(SYMBIAN)
     static void* stackBase = 0;
     if (stackBase == 0) {
         TThreadStackInfo info;
     static void* stackBase = 0;
     if (stackBase == 0) {
         TThreadStackInfo info;
@@ -494,7 +606,11 @@ static inline void* currentThreadStackBase()
         stackBase = (void*)info.iBase;
     }
     return (void*)stackBase;
         stackBase = (void*)info.iBase;
     }
     return (void*)stackBase;
-#elif PLATFORM(UNIX)
+#elif OS(HAIKU)
+    thread_info threadInfo;
+    get_thread_info(find_thread(NULL), &threadInfo);
+    return threadInfo.stack_end;
+#elif OS(UNIX)
     static void* stackBase = 0;
     static size_t stackSize = 0;
     static pthread_t stackThread;
     static void* stackBase = 0;
     static size_t stackSize = 0;
     static pthread_t stackThread;
@@ -502,7 +618,7 @@ static inline void* currentThreadStackBase()
     if (stackBase == 0 || thread != stackThread) {
         pthread_attr_t sattr;
         pthread_attr_init(&sattr);
     if (stackBase == 0 || thread != stackThread) {
         pthread_attr_t sattr;
         pthread_attr_init(&sattr);
-#if HAVE(PTHREAD_NP_H) || PLATFORM(NETBSD)
+#if HAVE(PTHREAD_NP_H) || OS(NETBSD)
         // e.g. on FreeBSD 5.4, neundorf@kde.org
         pthread_attr_get_np(thread, &sattr);
 #else
         // e.g. on FreeBSD 5.4, neundorf@kde.org
         pthread_attr_get_np(thread, &sattr);
 #else
@@ -516,7 +632,7 @@ static inline void* currentThreadStackBase()
         stackThread = thread;
     }
     return static_cast<char*>(stackBase) + stackSize;
         stackThread = thread;
     }
     return static_cast<char*>(stackBase) + stackSize;
-#elif PLATFORM(WINCE)
+#elif OS(WINCE)
     if (g_stackBase)
         return g_stackBase;
     else {
     if (g_stackBase)
         return g_stackBase;
     else {
@@ -532,11 +648,10 @@ static inline void* currentThreadStackBase()
 
 static inline PlatformThread getCurrentPlatformThread()
 {
 
 static inline PlatformThread getCurrentPlatformThread()
 {
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
     return pthread_mach_thread_np(pthread_self());
     return pthread_mach_thread_np(pthread_self());
-#elif PLATFORM(WIN_OS)
-    HANDLE threadHandle = pthread_getw32threadhandle_np(pthread_self());
-    return PlatformThread(GetCurrentThreadId(), threadHandle);
+#elif OS(WINDOWS)
+    return pthread_getw32threadhandle_np(pthread_self());
 #endif
 }
 
 #endif
 }
 
@@ -552,6 +667,8 @@ void Heap::makeUsableFromMultipleThreads()
 
 void Heap::registerThread()
 {
 
 void Heap::registerThread()
 {
+    ASSERT(!m_globalData->mainThreadOnly || isMainThread() || pthread_main_np());
+
     if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar))
         return;
 
     if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar))
         return;
 
@@ -603,12 +720,39 @@ void Heap::registerThread()
 
 #endif
 
 
 #endif
 
-#define IS_POINTER_ALIGNED(p) (((intptr_t)(p) & (sizeof(char*) - 1)) == 0)
+inline bool isPointerAligned(void* p)
+{
+    return (((intptr_t)(p) & (sizeof(char*) - 1)) == 0);
+}
+
+// Cell size needs to be a power of two for isPossibleCell to be valid.
+COMPILE_ASSERT(sizeof(CollectorCell) % 2 == 0, Collector_cell_size_is_power_of_two);
+
+#if USE(JSVALUE32)
+static bool isHalfCellAligned(void *p)
+{
+    return (((intptr_t)(p) & (CELL_MASK >> 1)) == 0);
+}
+
+static inline bool isPossibleCell(void* p)
+{
+    return isHalfCellAligned(p) && p;
+}
+
+#else
+
+static inline bool isCellAligned(void *p)
+{
+    return (((intptr_t)(p) & CELL_MASK) == 0);
+}
 
 
-// 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)
+static inline bool isPossibleCell(void* p)
+{
+    return isCellAligned(p) && p;
+}
+#endif // USE(JSVALUE32)
 
 
-void Heap::markConservatively(void* start, void* end)
+void Heap::markConservatively(MarkStack& markStack, void* start, void* end)
 {
     if (start > end) {
         void* tmp = start;
 {
     if (start > end) {
         void* tmp = start;
@@ -617,63 +761,55 @@ void Heap::markConservatively(void* start, void* end)
     }
 
     ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000);
     }
 
     ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000);
-    ASSERT(IS_POINTER_ALIGNED(start));
-    ASSERT(IS_POINTER_ALIGNED(end));
+    ASSERT(isPointerAligned(start));
+    ASSERT(isPointerAligned(end));
 
     char** p = static_cast<char**>(start);
     char** e = static_cast<char**>(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);
-
+    CollectorBlock** blocks = m_heap.blocks;
     while (p != e) {
         char* x = *p++;
     while (p != e) {
         char* x = *p++;
-        if (IS_HALF_CELL_ALIGNED(x) && x) {
+        if (isPossibleCell(x)) {
+            size_t usedBlocks;
             uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);
             xAsBits &= CELL_ALIGN_MASK;
             uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);
             xAsBits &= CELL_ALIGN_MASK;
+
             uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK;
             uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK;
+            const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);
+            if (offset > lastCellOffset)
+                continue;
+
             CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset);
             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;
-                }
+            usedBlocks = m_heap.usedBlocks;
+            for (size_t block = 0; block < usedBlocks; block++) {
+                if (blocks[block] != blockAddr)
+                    continue;
+                markStack.append(reinterpret_cast<JSCell*>(xAsBits));
+                markStack.drain();
             }
             }
-          
-            // 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 NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(MarkStack& markStack)
 {
     void* dummy;
     void* stackPointer = &dummy;
     void* stackBase = currentThreadStackBase();
 {
     void* dummy;
     void* stackPointer = &dummy;
     void* stackBase = currentThreadStackBase();
-    markConservatively(stackPointer, stackBase);
+    markConservatively(markStack, stackPointer, stackBase);
 }
 
 }
 
-void Heap::markCurrentThreadConservatively()
+#if COMPILER(GCC)
+#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
+#else
+#define REGISTER_BUFFER_ALIGNMENT
+#endif
+
+void Heap::markCurrentThreadConservatively(MarkStack& markStack)
 {
     // setjmp forces volatile registers onto the stack
 {
     // setjmp forces volatile registers onto the stack
-    jmp_buf registers;
+    jmp_buf registers REGISTER_BUFFER_ALIGNMENT;
 #if COMPILER(MSVC)
 #pragma warning(push)
 #pragma warning(disable: 4611)
 #if COMPILER(MSVC)
 #pragma warning(push)
 #pragma warning(disable: 4611)
@@ -683,17 +819,17 @@ void Heap::markCurrentThreadConservatively()
 #pragma warning(pop)
 #endif
 
 #pragma warning(pop)
 #endif
 
-    markCurrentThreadConservativelyInternal();
+    markCurrentThreadConservativelyInternal(markStack);
 }
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 
 static inline void suspendThread(const PlatformThread& platformThread)
 {
 }
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 
 static inline void suspendThread(const PlatformThread& platformThread)
 {
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
     thread_suspend(platformThread);
     thread_suspend(platformThread);
-#elif PLATFORM(WIN_OS)
-    SuspendThread(platformThread.handle);
+#elif OS(WINDOWS)
+    SuspendThread(platformThread);
 #else
 #error Need a way to suspend threads on this platform
 #endif
 #else
 #error Need a way to suspend threads on this platform
 #endif
@@ -701,10 +837,10 @@ static inline void suspendThread(const PlatformThread& platformThread)
 
 static inline void resumeThread(const PlatformThread& platformThread)
 {
 
 static inline void resumeThread(const PlatformThread& platformThread)
 {
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
     thread_resume(platformThread);
     thread_resume(platformThread);
-#elif PLATFORM(WIN_OS)
-    ResumeThread(platformThread.handle);
+#elif OS(WINDOWS)
+    ResumeThread(platformThread);
 #else
 #error Need a way to resume threads on this platform
 #endif
 #else
 #error Need a way to resume threads on this platform
 #endif
@@ -712,23 +848,23 @@ static inline void resumeThread(const PlatformThread& platformThread)
 
 typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
 
 
 typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
 
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 
 
-#if PLATFORM(X86)
+#if CPU(X86)
 typedef i386_thread_state_t PlatformThreadRegisters;
 typedef i386_thread_state_t PlatformThreadRegisters;
-#elif PLATFORM(X86_64)
+#elif CPU(X86_64)
 typedef x86_thread_state64_t PlatformThreadRegisters;
 typedef x86_thread_state64_t PlatformThreadRegisters;
-#elif PLATFORM(PPC)
+#elif CPU(PPC)
 typedef ppc_thread_state_t PlatformThreadRegisters;
 typedef ppc_thread_state_t PlatformThreadRegisters;
-#elif PLATFORM(PPC64)
+#elif CPU(PPC64)
 typedef ppc_thread_state64_t PlatformThreadRegisters;
 typedef ppc_thread_state64_t PlatformThreadRegisters;
-#elif PLATFORM(ARM)
+#elif CPU(ARM)
 typedef arm_thread_state_t PlatformThreadRegisters;
 #else
 #error Unknown Architecture
 #endif
 
 typedef arm_thread_state_t PlatformThreadRegisters;
 #else
 #error Unknown Architecture
 #endif
 
-#elif PLATFORM(WIN_OS)&& PLATFORM(X86)
+#elif OS(WINDOWS) && CPU(X86)
 typedef CONTEXT PlatformThreadRegisters;
 #else
 #error Need a thread register struct for this platform
 typedef CONTEXT PlatformThreadRegisters;
 #else
 #error Need a thread register struct for this platform
@@ -736,21 +872,21 @@ typedef CONTEXT PlatformThreadRegisters;
 
 static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
 {
 
 static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
 {
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 
 
-#if PLATFORM(X86)
+#if CPU(X86)
     unsigned user_count = sizeof(regs)/sizeof(int);
     thread_state_flavor_t flavor = i386_THREAD_STATE;
     unsigned user_count = sizeof(regs)/sizeof(int);
     thread_state_flavor_t flavor = i386_THREAD_STATE;
-#elif PLATFORM(X86_64)
+#elif CPU(X86_64)
     unsigned user_count = x86_THREAD_STATE64_COUNT;
     thread_state_flavor_t flavor = x86_THREAD_STATE64;
     unsigned user_count = x86_THREAD_STATE64_COUNT;
     thread_state_flavor_t flavor = x86_THREAD_STATE64;
-#elif PLATFORM(PPC) 
+#elif CPU(PPC) 
     unsigned user_count = PPC_THREAD_STATE_COUNT;
     thread_state_flavor_t flavor = PPC_THREAD_STATE;
     unsigned user_count = PPC_THREAD_STATE_COUNT;
     thread_state_flavor_t flavor = PPC_THREAD_STATE;
-#elif PLATFORM(PPC64)
+#elif CPU(PPC64)
     unsigned user_count = PPC_THREAD_STATE64_COUNT;
     thread_state_flavor_t flavor = PPC_THREAD_STATE64;
     unsigned user_count = PPC_THREAD_STATE64_COUNT;
     thread_state_flavor_t flavor = PPC_THREAD_STATE64;
-#elif PLATFORM(ARM)
+#elif CPU(ARM)
     unsigned user_count = ARM_THREAD_STATE_COUNT;
     thread_state_flavor_t flavor = ARM_THREAD_STATE;
 #else
     unsigned user_count = ARM_THREAD_STATE_COUNT;
     thread_state_flavor_t flavor = ARM_THREAD_STATE;
 #else
@@ -764,11 +900,11 @@ static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, P
         CRASH();
     }
     return user_count * sizeof(usword_t);
         CRASH();
     }
     return user_count * sizeof(usword_t);
-// end PLATFORM(DARWIN)
+// end OS(DARWIN)
 
 
-#elif PLATFORM(WIN_OS) && PLATFORM(X86)
+#elif OS(WINDOWS) && CPU(X86)
     regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
     regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
-    GetThreadContext(platformThread.handle, &regs);
+    GetThreadContext(platformThread, &regs);
     return sizeof(CONTEXT);
 #else
 #error Need a way to get thread registers on this platform
     return sizeof(CONTEXT);
 #else
 #error Need a way to get thread registers on this platform
@@ -777,17 +913,17 @@ static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, P
 
 static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
 {
 
 static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
 {
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 
 #if __DARWIN_UNIX03
 
 
 #if __DARWIN_UNIX03
 
-#if PLATFORM(X86)
+#if CPU(X86)
     return reinterpret_cast<void*>(regs.__esp);
     return reinterpret_cast<void*>(regs.__esp);
-#elif PLATFORM(X86_64)
+#elif CPU(X86_64)
     return reinterpret_cast<void*>(regs.__rsp);
     return reinterpret_cast<void*>(regs.__rsp);
-#elif PLATFORM(PPC) || PLATFORM(PPC64)
+#elif CPU(PPC) || CPU(PPC64)
     return reinterpret_cast<void*>(regs.__r1);
     return reinterpret_cast<void*>(regs.__r1);
-#elif PLATFORM(ARM)
+#elif CPU(ARM)
     return reinterpret_cast<void*>(regs.__sp);
 #else
 #error Unknown Architecture
     return reinterpret_cast<void*>(regs.__sp);
 #else
 #error Unknown Architecture
@@ -795,11 +931,11 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
 
 #else // !__DARWIN_UNIX03
 
 
 #else // !__DARWIN_UNIX03
 
-#if PLATFORM(X86)
+#if CPU(X86)
     return reinterpret_cast<void*>(regs.esp);
     return reinterpret_cast<void*>(regs.esp);
-#elif PLATFORM(X86_64)
+#elif CPU(X86_64)
     return reinterpret_cast<void*>(regs.rsp);
     return reinterpret_cast<void*>(regs.rsp);
-#elif (PLATFORM(PPC) || PLATFORM(PPC64))
+#elif CPU(PPC) || CPU(PPC64)
     return reinterpret_cast<void*>(regs.r1);
 #else
 #error Unknown Architecture
     return reinterpret_cast<void*>(regs.r1);
 #else
 #error Unknown Architecture
@@ -807,15 +943,15 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
 
 #endif // __DARWIN_UNIX03
 
 
 #endif // __DARWIN_UNIX03
 
-// end PLATFORM(DARWIN)
-#elif PLATFORM(X86) && PLATFORM(WIN_OS)
+// end OS(DARWIN)
+#elif CPU(X86) && OS(WINDOWS)
     return reinterpret_cast<void*>((uintptr_t) regs.Esp);
 #else
 #error Need a way to get the stack pointer for another thread on this platform
 #endif
 }
 
     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)
+void Heap::markOtherThreadConservatively(MarkStack& markStack, Thread* thread)
 {
     suspendThread(thread->platformThread);
 
 {
     suspendThread(thread->platformThread);
 
@@ -823,19 +959,19 @@ void Heap::markOtherThreadConservatively(Thread* thread)
     size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
 
     // mark the thread's registers
     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));
+    markConservatively(markStack, static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
 
     void* stackPointer = otherThreadStackPointer(regs);
 
     void* stackPointer = otherThreadStackPointer(regs);
-    markConservatively(stackPointer, thread->stackBase);
+    markConservatively(markStack, stackPointer, thread->stackBase);
 
     resumeThread(thread->platformThread);
 }
 
 #endif
 
 
     resumeThread(thread->platformThread);
 }
 
 #endif
 
-void Heap::markStackObjectsConservatively()
+void Heap::markStackObjectsConservatively(MarkStack& markStack)
 {
 {
-    markCurrentThreadConservatively();
+    markCurrentThreadConservatively(markStack);
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 
@@ -845,7 +981,7 @@ void Heap::markStackObjectsConservatively()
 
 #ifndef NDEBUG
         // Forbid malloc during the mark phase. Marking a thread suspends it, so 
 
 #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 
+        // a malloc inside markChildren() would risk a deadlock with a thread that had been 
         // suspended while holding the malloc lock.
         fastMallocForbid();
 #endif
         // suspended while holding the malloc lock.
         fastMallocForbid();
 #endif
@@ -853,7 +989,7 @@ void Heap::markStackObjectsConservatively()
         // 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()))
         // 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);
+                markOtherThreadConservatively(markStack, thread);
         }
 #ifndef NDEBUG
         fastMallocAllow();
         }
 #ifndef NDEBUG
         fastMallocAllow();
@@ -862,16 +998,6 @@ void Heap::markStackObjectsConservatively()
 #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);
 void Heap::protect(JSValue k)
 {
     ASSERT(k);
@@ -880,13 +1006,7 @@ void Heap::protect(JSValue k)
     if (!k.isCell())
         return;
 
     if (!k.isCell())
         return;
 
-    if (m_protectedValuesMutex)
-        m_protectedValuesMutex->lock();
-
     m_protectedValues.add(k.asCell());
     m_protectedValues.add(k.asCell());
-
-    if (m_protectedValuesMutex)
-        m_protectedValuesMutex->unlock();
 }
 
 void Heap::unprotect(JSValue k)
 }
 
 void Heap::unprotect(JSValue k)
@@ -897,138 +1017,80 @@ void Heap::unprotect(JSValue k)
     if (!k.isCell())
         return;
 
     if (!k.isCell())
         return;
 
-    if (m_protectedValuesMutex)
-        m_protectedValuesMutex->lock();
-
     m_protectedValues.remove(k.asCell());
     m_protectedValues.remove(k.asCell());
+}
 
 
-    if (m_protectedValuesMutex)
-        m_protectedValuesMutex->unlock();
+void Heap::markProtectedObjects(MarkStack& markStack)
+{
+    ProtectCountSet::iterator end = m_protectedValues.end();
+    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
+        markStack.append(it->first);
+        markStack.drain();
+    }
 }
 
 }
 
-Heap* Heap::heap(JSValue v)
+void Heap::clearMarkBits()
 {
 {
-    if (!v.isCell())
-        return 0;
-    return Heap::cellBlock(v.asCell())->heap;
+    for (size_t i = 0; i < m_heap.usedBlocks; ++i)
+        clearMarkBits(m_heap.blocks[i]);
 }
 
 }
 
-void Heap::markProtectedObjects()
+void Heap::clearMarkBits(CollectorBlock* block)
 {
 {
-    if (m_protectedValuesMutex)
-        m_protectedValuesMutex->lock();
+    // allocate assumes that the last cell in every block is marked.
+    block->marked.clearAll();
+    block->marked.set(HeapConstants::cellsPerBlock - 1);
+}
 
 
-    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();
-    }
+size_t Heap::markedCells(size_t startBlock, size_t startCell) const
+{
+    ASSERT(startBlock <= m_heap.usedBlocks);
+    ASSERT(startCell < HeapConstants::cellsPerBlock);
+
+    if (startBlock >= m_heap.usedBlocks)
+        return 0;
+
+    size_t result = 0;
+    result += m_heap.blocks[startBlock]->marked.count(startCell);
+    for (size_t i = startBlock + 1; i < m_heap.usedBlocks; ++i)
+        result += m_heap.blocks[i]->marked.count();
 
 
-    if (m_protectedValuesMutex)
-        m_protectedValuesMutex->unlock();
+    return result;
 }
 
 }
 
-template <HeapType heapType> size_t Heap::sweep()
+void 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;
+    ASSERT(m_heap.operationInProgress == NoOperation);
+    if (m_heap.operationInProgress != NoOperation)
+        CRASH();
+    m_heap.operationInProgress = Collection;
     
     
-    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));
+#if !ENABLE(JSC_ZOMBIES)
+    Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get();
 #endif
 #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*)));
-                }
-            }
+
+    DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell);
+    DeadObjectIterator end(m_heap, m_heap.usedBlocks);
+    for ( ; it != end; ++it) {
+        JSCell* cell = *it;
+#if ENABLE(JSC_ZOMBIES)
+        if (!cell->isZombie()) {
+            const ClassInfo* info = cell->classInfo();
+            cell->~JSCell();
+            new (cell) JSZombie(info, JSZombie::leakedZombieStructure());
+            Heap::markCell(cell);
         }
         }
+#else
+        cell->~JSCell();
+        // Callers of sweep assume it's safe to mark any cell in the heap.
+        new (cell) JSCell(dummyMarkableCellStructure);
+#endif
     }
     }
-    
-    if (heap.numLiveObjects != numLiveObjects)
-        heap.firstBlockWithPossibleSpace = 0;
-        
-    heap.numLiveObjects = numLiveObjects;
-    heap.numLiveObjectsAtLastCollect = numLiveObjects;
-    heap.extraCost = 0;
-    return numLiveObjects;
+
+    m_heap.operationInProgress = NoOperation;
 }
 }
-    
-bool Heap::collect()
+
+void Heap::markRoots()
 {
 #ifndef NDEBUG
     if (m_globalData->isSharedInstance) {
 {
 #ifndef NDEBUG
     if (m_globalData->isSharedInstance) {
@@ -1037,64 +1099,62 @@ bool Heap::collect()
     }
 #endif
 
     }
 #endif
 
-    ASSERT((primaryHeap.operationInProgress == NoOperation) | (numberHeap.operationInProgress == NoOperation));
-    if ((primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation))
+    ASSERT(m_heap.operationInProgress == NoOperation);
+    if (m_heap.operationInProgress != NoOperation)
         CRASH();
 
         CRASH();
 
-    JAVASCRIPTCORE_GC_BEGIN();
-    primaryHeap.operationInProgress = Collection;
-    numberHeap.operationInProgress = Collection;
+    m_heap.operationInProgress = Collection;
+
+    MarkStack& markStack = m_globalData->markStack;
+
+    // Reset mark bits.
+    clearMarkBits();
 
 
-    // MARK: first mark all referenced objects recursively starting out from the set of root objects
+    // Mark stack roots.
+    markStackObjectsConservatively(markStack);
+    m_globalData->interpreter->registerFile().markCallFrames(markStack, this);
 
 
-    markStackObjectsConservatively();
-    markProtectedObjects();
+    // Mark explicitly registered roots.
+    markProtectedObjects(markStack);
+
+    // Mark misc. other roots.
     if (m_markListSet && m_markListSet->size())
     if (m_markListSet && m_markListSet->size())
-        MarkedArgumentBuffer::markLists(*m_markListSet);
-    if (m_globalData->exception && !m_globalData->exception.marked())
-        m_globalData->exception.mark();
-    m_globalData->interpreter->registerFile().markCallFrames(this);
-    m_globalData->smallStrings.mark();
-    if (m_globalData->scopeNodeBeingReparsed)
-        m_globalData->scopeNodeBeingReparsed->mark();
+        MarkedArgumentBuffer::markLists(markStack, *m_markListSet);
+    if (m_globalData->exception)
+        markStack.append(m_globalData->exception);
+    if (m_globalData->functionCodeBlockBeingReparsed)
+        m_globalData->functionCodeBlockBeingReparsed->markAggregate(markStack);
     if (m_globalData->firstStringifierToMark)
     if (m_globalData->firstStringifierToMark)
-        JSONObject::markStringifiers(m_globalData->firstStringifierToMark);
-
-    JAVASCRIPTCORE_GC_MARKED();
+        JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark);
 
 
-    size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
-    size_t numLiveObjects = sweep<PrimaryHeap>();
-    numLiveObjects += sweep<NumberHeap>();
+    // Mark the small strings cache last, since it will clear itself if nothing
+    // else has marked it.
+    m_globalData->smallStrings.markChildren(markStack);
 
 
-    primaryHeap.operationInProgress = NoOperation;
-    numberHeap.operationInProgress = NoOperation;
-    JAVASCRIPTCORE_GC_END(originalLiveObjects, numLiveObjects);
+    markStack.drain();
+    markStack.compact();
 
 
-    return numLiveObjects < originalLiveObjects;
+    m_heap.operationInProgress = NoOperation;
 }
 
 }
 
-size_t Heap::objectCount() 
+size_t Heap::objectCount() const
 {
 {
-    return primaryHeap.numLiveObjects + numberHeap.numLiveObjects - m_globalData->smallStrings.count(); 
+    return m_heap.nextBlock * HeapConstants::cellsPerBlock // allocated full blocks
+           + m_heap.nextCell // allocated cells in current block
+           + markedCells(m_heap.nextBlock, m_heap.nextCell) // marked cells in remainder of m_heap
+           - m_heap.usedBlocks; // 1 cell per block is a dummy sentinel
 }
 
 }
 
-template <HeapType heapType> 
-static void addToStatistics(Heap::Statistics& statistics, const CollectorHeap& heap)
+void Heap::addToStatistics(Heap::Statistics& statistics) const
 {
 {
-    typedef HeapConstants<heapType> HC;
-    for (size_t i = 0; i < heap.usedBlocks; ++i) {
-        if (heap.blocks[i]) {
-            statistics.size += BLOCK_SIZE;
-            statistics.free += (HC::cellsPerBlock - heap.blocks[i]->usedCells) * HC::cellSize;
-        }
-    }
+    statistics.size += m_heap.usedBlocks * BLOCK_SIZE;
+    statistics.free += m_heap.usedBlocks * BLOCK_SIZE - (objectCount() * HeapConstants::cellSize);
 }
 
 Heap::Statistics Heap::statistics() const
 {
     Statistics statistics = { 0, 0 };
 }
 
 Heap::Statistics Heap::statistics() const
 {
     Statistics statistics = { 0, 0 };
-    JSC::addToStatistics<PrimaryHeap>(statistics, primaryHeap);
-    JSC::addToStatistics<NumberHeap>(statistics, numberHeap);
+    addToStatistics(statistics);
     return statistics;
 }
 
     return statistics;
 }
 
@@ -1113,9 +1173,6 @@ size_t Heap::globalObjectCount()
 
 size_t Heap::protectedGlobalObjectCount()
 {
 
 size_t Heap::protectedGlobalObjectCount()
 {
-    if (m_protectedValuesMutex)
-        m_protectedValuesMutex->lock();
-
     size_t count = 0;
     if (JSGlobalObject* head = m_globalData->head) {
         JSGlobalObject* o = head;
     size_t count = 0;
     if (JSGlobalObject* head = m_globalData->head) {
         JSGlobalObject* o = head;
@@ -1126,23 +1183,12 @@ size_t Heap::protectedGlobalObjectCount()
         } while (o != head);
     }
 
         } while (o != head);
     }
 
-    if (m_protectedValuesMutex)
-        m_protectedValuesMutex->unlock();
-
     return count;
 }
 
 size_t Heap::protectedObjectCount()
 {
     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;
+    return m_protectedValues.size();
 }
 
 static const char* typeName(JSCell* cell)
 }
 
 static const char* typeName(JSCell* cell)
@@ -1155,8 +1201,12 @@ static const char* typeName(JSCell* cell)
 #endif
     if (cell->isGetterSetter())
         return "gettersetter";
 #endif
     if (cell->isGetterSetter())
         return "gettersetter";
+    if (cell->isAPIValueWrapper())
+        return "value wrapper";
+    if (cell->isPropertyNameIterator())
+        return "for-in iterator";
     ASSERT(cell->isObject());
     ASSERT(cell->isObject());
-    const ClassInfo* info = static_cast<JSObject*>(cell)->classInfo();
+    const ClassInfo* info = cell->classInfo();
     return info ? info->className : "Object";
 }
 
     return info ? info->className : "Object";
 }
 
@@ -1164,32 +1214,70 @@ HashCountedSet<const char*>* Heap::protectedObjectTypeCounts()
 {
     HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
 
 {
     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));
 
     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 counts;
 }
 
 bool Heap::isBusy()
 {
-    return (primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation);
+    return m_heap.operationInProgress != NoOperation;
+}
+
+void Heap::reset()
+{
+    JAVASCRIPTCORE_GC_BEGIN();
+
+    markRoots();
+
+    JAVASCRIPTCORE_GC_MARKED();
+
+    m_heap.nextCell = 0;
+    m_heap.nextBlock = 0;
+    m_heap.nextNumber = 0;
+    m_heap.extraCost = 0;
+#if ENABLE(JSC_ZOMBIES)
+    sweep();
+#endif
+    resizeBlocks();
+
+    JAVASCRIPTCORE_GC_END();
+}
+
+void Heap::collectAllGarbage()
+{
+    JAVASCRIPTCORE_GC_BEGIN();
+
+    // If the last iteration through the heap deallocated blocks, we need
+    // to clean up remaining garbage before marking. Otherwise, the conservative
+    // marking mechanism might follow a pointer to unmapped memory.
+    if (m_heap.didShrink)
+        sweep();
+
+    markRoots();
+
+    JAVASCRIPTCORE_GC_MARKED();
+
+    m_heap.nextCell = 0;
+    m_heap.nextBlock = 0;
+    m_heap.nextNumber = 0;
+    m_heap.extraCost = 0;
+    sweep();
+    resizeBlocks();
+
+    JAVASCRIPTCORE_GC_END();
 }
 
 }
 
-Heap::iterator Heap::primaryHeapBegin()
+LiveObjectIterator Heap::primaryHeapBegin()
 {
 {
-    return iterator(primaryHeap.blocks, primaryHeap.blocks + primaryHeap.usedBlocks);
+    return LiveObjectIterator(m_heap, 0);
 }
 
 }
 
-Heap::iterator Heap::primaryHeapEnd()
+LiveObjectIterator Heap::primaryHeapEnd()
 {
 {
-    return iterator(primaryHeap.blocks + primaryHeap.usedBlocks, primaryHeap.blocks + primaryHeap.usedBlocks);
+    return LiveObjectIterator(m_heap, m_heap.usedBlocks);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 8c490094df52957cc6f65e29d3d9ec60fffe20db..9d73e5eb92441fec2ebd846eb3e8bf0c57861eb7 100644 (file)
@@ -28,9 +28,9 @@
 #include <wtf/HashSet.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/HashSet.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/OwnPtr.h>
+#include <wtf/StdLibExtras.h>
 #include <wtf/Threading.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
 #if ENABLE(JSC_MULTIPLE_THREADS)
 #include <pthread.h>
 #endif
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class MarkedArgumentBuffer;
     class CollectorBlock;
     class JSCell;
     class JSGlobalData;
     class JSValue;
     class CollectorBlock;
     class JSCell;
     class JSGlobalData;
     class JSValue;
+    class MarkedArgumentBuffer;
+    class MarkStack;
 
     enum OperationInProgress { NoOperation, Allocation, Collection };
 
     enum OperationInProgress { NoOperation, Allocation, Collection };
-    enum HeapType { PrimaryHeap, NumberHeap };
 
 
-    template <HeapType> class CollectorHeapIterator;
+    class LiveObjectIterator;
 
     struct CollectorHeap {
 
     struct CollectorHeap {
+        size_t nextBlock;
+        size_t nextCell;
         CollectorBlock** blocks;
         CollectorBlock** blocks;
+        
+        void* nextNumber;
+
         size_t numBlocks;
         size_t usedBlocks;
         size_t numBlocks;
         size_t usedBlocks;
-        size_t firstBlockWithPossibleSpace;
 
 
-        size_t numLiveObjects;
-        size_t numLiveObjectsAtLastCollect;
         size_t extraCost;
         size_t extraCost;
+        bool didShrink;
 
         OperationInProgress operationInProgress;
     };
 
 
         OperationInProgress operationInProgress;
     };
 
-    class Heap : Noncopyable {
+    class Heap : public Noncopyable {
     public:
         class Thread;
     public:
         class Thread;
-        typedef CollectorHeapIterator<PrimaryHeap> iterator;
 
         void destroy();
 
 
         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);
 
         void* allocateNumber(size_t);
         void* allocate(size_t);
 
-        bool collect();
         bool isBusy(); // true if an allocation or collection is in progress
         bool isBusy(); // true if an allocation or collection is in progress
+        void collectAllGarbage();
 
 
-        static const size_t minExtraCostSize = 256;
+        static const size_t minExtraCost = 256;
+        static const size_t maxExtraCost = 1024 * 1024;
 
         void reportExtraMemoryCost(size_t cost);
 
 
         void reportExtraMemoryCost(size_t cost);
 
-        size_t objectCount();
+        size_t objectCount() const;
         struct Statistics {
             size_t size;
             size_t free;
         };
         Statistics statistics() const;
 
         struct Statistics {
             size_t size;
             size_t free;
         };
         Statistics statistics() const;
 
-        void setGCProtectNeedsLocking();
         void protect(JSValue);
         void unprotect(JSValue);
 
         static Heap* heap(JSValue); // 0 for immediate values
         void protect(JSValue);
         void unprotect(JSValue);
 
         static Heap* heap(JSValue); // 0 for immediate values
+        static Heap* heap(JSCell*);
 
         size_t globalObjectCount();
         size_t protectedObjectCount();
 
         size_t globalObjectCount();
         size_t protectedObjectCount();
@@ -111,20 +106,19 @@ namespace JSC {
         static bool isCellMarked(const JSCell*);
         static void markCell(JSCell*);
 
         static bool isCellMarked(const JSCell*);
         static void markCell(JSCell*);
 
-        void markConservatively(void* start, void* end);
+        void markConservatively(MarkStack&, void* start, void* end);
 
         HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
 
         JSGlobalData* globalData() const { return m_globalData; }
         static bool isNumber(JSCell*);
         
 
         HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
 
         JSGlobalData* globalData() const { return m_globalData; }
         static bool isNumber(JSCell*);
         
-        // Iterators for the object heap.
-        iterator primaryHeapBegin();
-        iterator primaryHeapEnd();
+        LiveObjectIterator primaryHeapBegin();
+        LiveObjectIterator primaryHeapEnd();
 
     private:
 
     private:
-        template <HeapType heapType> void* heapAllocate(size_t);
-        template <HeapType heapType> size_t sweep();
+        void reset();
+        void sweep();
         static CollectorBlock* cellBlock(const JSCell*);
         static size_t cellOffset(const JSCell*);
 
         static CollectorBlock* cellBlock(const JSCell*);
         static size_t cellOffset(const JSCell*);
 
@@ -132,19 +126,32 @@ namespace JSC {
         Heap(JSGlobalData*);
         ~Heap();
 
         Heap(JSGlobalData*);
         ~Heap();
 
+        NEVER_INLINE CollectorBlock* allocateBlock();
+        NEVER_INLINE void freeBlock(size_t);
+        NEVER_INLINE void freeBlockPtr(CollectorBlock*);
+        void freeBlocks();
+        void resizeBlocks();
+        void growBlocks(size_t neededBlocks);
+        void shrinkBlocks(size_t neededBlocks);
+        void clearMarkBits();
+        void clearMarkBits(CollectorBlock*);
+        size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const;
+
         void recordExtraCost(size_t);
         void recordExtraCost(size_t);
-        void markProtectedObjects();
-        void markCurrentThreadConservatively();
-        void markCurrentThreadConservativelyInternal();
-        void markOtherThreadConservatively(Thread*);
-        void markStackObjectsConservatively();
+
+        void addToStatistics(Statistics&) const;
+
+        void markRoots();
+        void markProtectedObjects(MarkStack&);
+        void markCurrentThreadConservatively(MarkStack&);
+        void markCurrentThreadConservativelyInternal(MarkStack&);
+        void markOtherThreadConservatively(MarkStack&, Thread*);
+        void markStackObjectsConservatively(MarkStack&);
 
         typedef HashCountedSet<JSCell*> ProtectCountSet;
 
 
         typedef HashCountedSet<JSCell*> ProtectCountSet;
 
-        CollectorHeap primaryHeap;
-        CollectorHeap numberHeap;
+        CollectorHeap m_heap;
 
 
-        OwnPtr<Mutex> m_protectedValuesMutex; // Only non-null if the client explicitly requested it via setGCPrtotectNeedsLocking().
         ProtectCountSet m_protectedValues;
 
         HashSet<MarkedArgumentBuffer*>* m_markListSet;
         ProtectCountSet m_protectedValues;
 
         HashSet<MarkedArgumentBuffer*>* m_markListSet;
@@ -174,7 +181,7 @@ namespace JSC {
 #endif
     template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; };
 
 #endif
     template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; };
 
-    const size_t BLOCK_SIZE = 16 * 4096; // 64k
+    const size_t BLOCK_SIZE = 64 * 1024; // 64k
 
     // derived constants
     const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
 
     // derived constants
     const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
@@ -185,87 +192,60 @@ namespace JSC {
     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 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 CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells.
+    
     const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
     const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
     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 CollectorBitmap {
         uint32_t bits[BITMAP_WORDS];
         bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } 
         void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } 
         void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } 
         void clearAll() { memset(bits, 0, sizeof(bits)); }
+        size_t count(size_t startCell = 0)
+        {
+            size_t result = 0;
+            for ( ; (startCell & 0x1F) != 0; ++startCell) {
+                if (get(startCell))
+                    ++result;
+            }
+            for (size_t i = startCell >> 5; i < BITMAP_WORDS; ++i)
+                result += WTF::bitCount(bits[i]);
+            return result;
+        }
+        size_t isEmpty() // Much more efficient than testing count() == 0.
+        {
+            for (size_t i = 0; i < BITMAP_WORDS; ++i)
+                if (bits[i] != 0)
+                    return false;
+            return true;
+        }
     };
   
     struct CollectorCell {
     };
   
     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;
+        double memory[CELL_ARRAY_LENGTH];
     };
 
     class CollectorBlock {
     public:
         CollectorCell cells[CELLS_PER_BLOCK];
     };
 
     class CollectorBlock {
     public:
         CollectorCell cells[CELLS_PER_BLOCK];
-        uint32_t usedCells;
-        CollectorCell* freeList;
         CollectorBitmap marked;
         Heap* heap;
         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> {
+    struct HeapConstants {
         static const size_t cellSize = CELL_SIZE;
         static const size_t cellsPerBlock = CELLS_PER_BLOCK;
         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;
     };
 
         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 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 size_t Heap::cellOffset(const JSCell* cell)
     {
         return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
@@ -283,8 +263,20 @@ namespace JSC {
 
     inline void Heap::reportExtraMemoryCost(size_t cost)
     {
 
     inline void Heap::reportExtraMemoryCost(size_t cost)
     {
-        if (cost > minExtraCostSize) 
-            recordExtraCost(cost / (CELL_SIZE * 2)); 
+        if (cost > minExtraCost) 
+            recordExtraCost(cost);
+    }
+    
+    inline void* Heap::allocateNumber(size_t s)
+    {
+        if (void* result = m_heap.nextNumber) {
+            m_heap.nextNumber = 0;
+            return result;
+        }
+
+        void* result = allocate(s);
+        m_heap.nextNumber = static_cast<char*>(result) + (CELL_SIZE / 2);
+        return result;
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index e38a8524cdc533b4daba9f78bd1d7fb1d7423d1d..e4f2f91acd11207360e9a18295270013f0a4fcc7 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    template <HeapType heapType> class CollectorHeapIterator {
+    class CollectorHeapIterator {
     public:
     public:
-        CollectorHeapIterator(CollectorBlock** block, CollectorBlock** endBlock);
-
-        bool operator!=(const CollectorHeapIterator<heapType>& other) { return m_block != other.m_block || m_cell != other.m_cell; }
-        CollectorHeapIterator<heapType>& operator++();
+        bool operator!=(const CollectorHeapIterator& other);
         JSCell* operator*() const;
     
         JSCell* operator*() const;
     
-    private:
-        typedef typename HeapConstants<heapType>::Block Block;
-        typedef typename HeapConstants<heapType>::Cell Cell;
-
-        Block** m_block;
-        Block** m_endBlock;
-        Cell* m_cell;
-        Cell* m_endCell;
+    protected:
+        CollectorHeapIterator(CollectorHeap&, size_t startBlock, size_t startCell);
+        void advance(size_t cellsPerBlock);
+
+        CollectorHeap& m_heap;
+        size_t m_block;
+        size_t m_cell;
+    };
+
+    class LiveObjectIterator : public CollectorHeapIterator {
+    public:
+        LiveObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
+        LiveObjectIterator& operator++();
+    };
+
+    class DeadObjectIterator : public CollectorHeapIterator {
+    public:
+        DeadObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
+        DeadObjectIterator& operator++();
+    };
+
+    class ObjectIterator : public CollectorHeapIterator {
+    public:
+        ObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
+        ObjectIterator& operator++();
     };
 
     };
 
-    template <HeapType heapType> 
-    CollectorHeapIterator<heapType>::CollectorHeapIterator(CollectorBlock** block, CollectorBlock** endBlock)
-        : m_block(reinterpret_cast<Block**>(block))
-        , m_endBlock(reinterpret_cast<Block**>(endBlock))
-        , m_cell(m_block == m_endBlock ? 0 : (*m_block)->cells)
-        , m_endCell(m_block == m_endBlock ? 0 : (*m_block)->cells + HeapConstants<heapType>::cellsPerBlock)
+    inline CollectorHeapIterator::CollectorHeapIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
+        : m_heap(heap)
+        , m_block(startBlock)
+        , m_cell(startCell)
+    {
+    }
+
+    inline bool CollectorHeapIterator::operator!=(const CollectorHeapIterator& other)
+    {
+        return m_block != other.m_block || m_cell != other.m_cell;
+    }
+
+    inline JSCell* CollectorHeapIterator::operator*() const
+    {
+        return reinterpret_cast<JSCell*>(m_heap.blocks[m_block]->cells + m_cell);
+    }
+    
+    inline void CollectorHeapIterator::advance(size_t cellsPerBlock)
+    {
+        ++m_cell;
+        if (m_cell == cellsPerBlock) {
+            m_cell = 0;
+            ++m_block;
+        }
+    }
+
+    inline LiveObjectIterator::LiveObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
+        : CollectorHeapIterator(heap, startBlock, startCell - 1)
+    {
+        ++(*this);
+    }
+
+    inline LiveObjectIterator& LiveObjectIterator::operator++()
+    {
+        if (m_block < m_heap.nextBlock || m_cell < m_heap.nextCell) {
+            advance(HeapConstants::cellsPerBlock);
+            return *this;
+        }
+
+        do {
+            advance(HeapConstants::cellsPerBlock);
+        } while (m_block < m_heap.usedBlocks && !m_heap.blocks[m_block]->marked.get(m_cell));
+        return *this;
+    }
+
+    inline DeadObjectIterator::DeadObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
+        : CollectorHeapIterator(heap, startBlock, startCell - 1)
     {
     {
-        if (m_cell && m_cell->u.freeCell.zeroIfFree == 0)
-            ++*this;
+        ++(*this);
     }
 
     }
 
-    template <HeapType heapType> 
-    CollectorHeapIterator<heapType>& CollectorHeapIterator<heapType>::operator++()
+    inline DeadObjectIterator& DeadObjectIterator::operator++()
     {
         do {
     {
         do {
-            for (++m_cell; m_cell != m_endCell; ++m_cell)
-                if (m_cell->u.freeCell.zeroIfFree != 0) {
-                    return *this;
-                }
-
-            if (++m_block != m_endBlock) {
-                m_cell = (*m_block)->cells;
-                m_endCell = (*m_block)->cells + HeapConstants<heapType>::cellsPerBlock;
-            }
-        } while(m_block != m_endBlock);
-
-        m_cell = 0;
+            advance(HeapConstants::cellsPerBlock);
+            ASSERT(m_block > m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell >= m_heap.nextCell));
+        } while (m_block < m_heap.usedBlocks && m_heap.blocks[m_block]->marked.get(m_cell));
         return *this;
     }
 
         return *this;
     }
 
-    template <HeapType heapType> 
-    JSCell* CollectorHeapIterator<heapType>::operator*() const
+    inline ObjectIterator::ObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
+        : CollectorHeapIterator(heap, startBlock, startCell - 1)
     {
     {
-        return reinterpret_cast<JSCell*>(m_cell);
+        ++(*this);
+    }
+
+    inline ObjectIterator& ObjectIterator::operator++()
+    {
+        advance(HeapConstants::cellsPerBlock);
+        return *this;
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index 408d81903755161a0eff1bfe7c42db8e53762a10..de24f4a0d4847b5a2a89896e964d034bad717f6a 100644 (file)
     macro(callee) \
     macro(caller) \
     macro(compile) \
     macro(callee) \
     macro(caller) \
     macro(compile) \
+    macro(configurable) \
     macro(constructor) \
     macro(constructor) \
+    macro(create) \
+    macro(defineProperty) \
+    macro(defineProperties) \
+    macro(enumerable) \
     macro(eval) \
     macro(exec) \
     macro(fromCharCode) \
     macro(global) \
     macro(eval) \
     macro(exec) \
     macro(fromCharCode) \
     macro(global) \
+    macro(get) \
+    macro(getPrototypeOf) \
+    macro(getOwnPropertyDescriptor) \
+    macro(getOwnPropertyNames) \
     macro(hasOwnProperty) \
     macro(ignoreCase) \
     macro(index) \
     macro(input) \
     macro(hasOwnProperty) \
     macro(ignoreCase) \
     macro(index) \
     macro(input) \
+    macro(isArray) \
     macro(isPrototypeOf) \
     macro(isPrototypeOf) \
+    macro(keys) \
     macro(length) \
     macro(message) \
     macro(multiline) \
     macro(length) \
     macro(message) \
     macro(multiline) \
@@ -55,6 +66,7 @@
     macro(parse) \
     macro(propertyIsEnumerable) \
     macro(prototype) \
     macro(parse) \
     macro(propertyIsEnumerable) \
     macro(prototype) \
+    macro(set) \
     macro(source) \
     macro(test) \
     macro(toExponential) \
     macro(source) \
     macro(test) \
     macro(toExponential) \
     macro(toPrecision) \
     macro(toString) \
     macro(UTC) \
     macro(toPrecision) \
     macro(toString) \
     macro(UTC) \
+    macro(value) \
     macro(valueOf) \
     macro(valueOf) \
+    macro(writable) \
     macro(displayName)
 
 namespace JSC {
 
     macro(displayName)
 
 namespace JSC {
 
-    class CommonIdentifiers : Noncopyable {
+    class CommonIdentifiers : public Noncopyable {
     private:
         CommonIdentifiers(JSGlobalData*);
         friend class JSGlobalData;
     private:
         CommonIdentifiers(JSGlobalData*);
         friend class JSGlobalData;
index b8b15819d59315f2aef1b4fc49e1472346a1df56..2f88df95d8cd6d118dab96598eedb6dad7dd3285 100644 (file)
 #include "Debugger.h"
 #include <stdio.h>
 
 #include "Debugger.h"
 #include <stdio.h>
 
-#if !PLATFORM(WIN_OS)
-#include <unistd.h>
-#endif
-
 namespace JSC {
 
 Completion checkSyntax(ExecState* exec, const SourceCode& source)
 {
     JSLock lock(exec);
 namespace JSC {
 
 Completion checkSyntax(ExecState* exec, const SourceCode& source)
 {
     JSLock lock(exec);
+    ASSERT(exec->globalData().identifierTable == currentIdentifierTable());
 
 
-    int errLine;
-    UString errMsg;
+    RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
+    JSObject* error = program->checkSyntax(exec);
+    if (error)
+        return Completion(Throw, error);
 
 
-    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 evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue)
 {
     JSLock lock(exec);
     return Completion(Normal);
 }
 
 Completion 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);
+    ASSERT(exec->globalData().identifierTable == currentIdentifierTable());
 
 
-    if (!programNode)
-        return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
+    RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
+    JSObject* error = program->compile(exec, scopeChain.node());
+    if (error)
+        return Completion(Throw, error);
 
     JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
 
     JSValue exception;
 
     JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
 
     JSValue exception;
-    JSValue result = exec->interpreter()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception);
+    JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain.node(), thisObj, &exception);
 
     if (exception) {
         if (exception.isObject() && asObject(exception)->isWatchdogException())
 
     if (exception) {
         if (exception.isObject() && asObject(exception)->isWatchdogException())
index 9d580d5799cfa3f3ac97441867a7071279a19e0a..6b954a629e518b28e4783c817f86cc32b9431603 100644 (file)
@@ -33,7 +33,7 @@ namespace JSC {
 
     class ArgList;
     class ExecState;
 
     class ArgList;
     class ExecState;
-    class FunctionBodyNode;
+    class FunctionExecutable;
     class JSObject;
     class JSValue;
     class ScopeChainNode;
     class JSObject;
     class JSValue;
     class ScopeChainNode;
@@ -51,7 +51,7 @@ namespace JSC {
             NativeConstructor function;
         } native;
         struct {
             NativeConstructor function;
         } native;
         struct {
-            FunctionBodyNode* functionBody;
+            FunctionExecutable* functionExecutable;
             ScopeChainNode* scopeChain;
         } js;
     };
             ScopeChainNode* scopeChain;
         } js;
     };
index 6d7d934062c354302058c378c3a2b25813a0c5d5..2e476b3b756be2515a43d613bf34a614997dbb86 100644 (file)
@@ -35,8 +35,8 @@
 #include <wtf/DateMath.h>
 #include <wtf/MathExtras.h>
 
 #include <wtf/DateMath.h>
 #include <wtf/MathExtras.h>
 
-#if PLATFORM(WINCE) && !PLATFORM(QT)
-extern "C" time_t time(time_t* timer); //provided by libce
+#if OS(WINCE) && !PLATFORM(QT)
+extern "C" time_t time(time_t* timer); // Provided by libce.
 #endif
 
 #if HAVE(SYS_TIME_H)
 #endif
 
 #if HAVE(SYS_TIME_H)
@@ -51,15 +51,13 @@ using namespace WTF;
 
 namespace JSC {
 
 
 namespace JSC {
 
-// TODO: MakeTime (15.9.11.1) etc. ?
-
 ASSERT_CLASS_FITS_IN_CELL(DateConstructor);
 
 static JSValue JSC_HOST_CALL dateParse(ExecState*, JSObject*, JSValue, const ArgList&);
 static JSValue JSC_HOST_CALL dateNow(ExecState*, JSObject*, JSValue, const ArgList&);
 static JSValue JSC_HOST_CALL dateUTC(ExecState*, JSObject*, JSValue, const ArgList&);
 
 ASSERT_CLASS_FITS_IN_CELL(DateConstructor);
 
 static JSValue JSC_HOST_CALL dateParse(ExecState*, JSObject*, JSValue, const ArgList&);
 static JSValue JSC_HOST_CALL dateNow(ExecState*, JSObject*, JSValue, const ArgList&);
 static JSValue JSC_HOST_CALL dateUTC(ExecState*, JSObject*, JSValue, const ArgList&);
 
-DateConstructor::DateConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype)
+DateConstructor::DateConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype)
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, datePrototype->classInfo()->className))
 {
       putDirectWithoutTransition(exec->propertyNames().prototype, datePrototype, DontEnum|DontDelete|ReadOnly);
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, datePrototype->classInfo()->className))
 {
       putDirectWithoutTransition(exec->propertyNames().prototype, datePrototype, DontEnum|DontDelete|ReadOnly);
@@ -79,14 +77,14 @@ JSObject* constructDate(ExecState* exec, const ArgList& args)
     double value;
 
     if (numArgs == 0) // new Date() ECMA 15.9.3.3
     double value;
 
     if (numArgs == 0) // new Date() ECMA 15.9.3.3
-        value = getCurrentUTCTime();
+        value = jsCurrentTime();
     else if (numArgs == 1) {
     else if (numArgs == 1) {
-        if (args.at(0).isObject(&DateInstance::info))
+        if (args.at(0).inherits(&DateInstance::info))
             value = asDateInstance(args.at(0))->internalNumber();
         else {
             JSValue primitive = args.at(0).toPrimitive(exec);
             if (primitive.isString())
             value = asDateInstance(args.at(0))->internalNumber();
         else {
             JSValue primitive = args.at(0).toPrimitive(exec);
             if (primitive.isString())
-                value = parseDate(primitive.getString());
+                value = parseDate(exec, primitive.getString(exec));
             else
                 value = primitive.toNumber(exec);
         }
             else
                 value = primitive.toNumber(exec);
         }
@@ -100,23 +98,21 @@ JSObject* constructDate(ExecState* exec, const ArgList& args)
                 || (numArgs >= 7 && isnan(args.at(6).toNumber(exec))))
             value = NaN;
         else {
                 || (numArgs >= 7 && isnan(args.at(6).toNumber(exec))))
             value = NaN;
         else {
-          GregorianDateTime t;
-          int year = args.at(0).toInt32(exec);
-          t.year = (year >= 0 && year <= 99) ? year : year - 1900;
-          t.month = args.at(1).toInt32(exec);
-          t.monthDay = (numArgs >= 3) ? args.at(2).toInt32(exec) : 1;
-          t.hour = args.at(3).toInt32(exec);
-          t.minute = args.at(4).toInt32(exec);
-          t.second = args.at(5).toInt32(exec);
-          t.isDST = -1;
-          double ms = (numArgs >= 7) ? args.at(6).toNumber(exec) : 0;
-          value = gregorianDateTimeToMS(t, ms, false);
+            GregorianDateTime t;
+            int year = args.at(0).toInt32(exec);
+            t.year = (year >= 0 && year <= 99) ? year : year - 1900;
+            t.month = args.at(1).toInt32(exec);
+            t.monthDay = (numArgs >= 3) ? args.at(2).toInt32(exec) : 1;
+            t.hour = args.at(3).toInt32(exec);
+            t.minute = args.at(4).toInt32(exec);
+            t.second = args.at(5).toInt32(exec);
+            t.isDST = -1;
+            double ms = (numArgs >= 7) ? args.at(6).toNumber(exec) : 0;
+            value = gregorianDateTimeToMS(exec, t, ms, false);
         }
     }
 
         }
     }
 
-    DateInstance* result = new (exec) DateInstance(exec->lexicalGlobalObject()->dateStructure());
-    result->setInternalValue(jsNumber(exec, timeClip(value)));
-    return result;
+    return new (exec) DateInstance(exec, value);
 }
     
 static JSObject* constructWithDateConstructor(ExecState* exec, JSObject*, const ArgList& args)
 }
     
 static JSObject* constructWithDateConstructor(ExecState* exec, JSObject*, const ArgList& args)
@@ -136,8 +132,12 @@ static JSValue JSC_HOST_CALL callDate(ExecState* exec, JSObject*, JSValue, const
     time_t localTime = time(0);
     tm localTM;
     getLocalTime(&localTime, &localTM);
     time_t localTime = time(0);
     tm localTM;
     getLocalTime(&localTime, &localTM);
-    GregorianDateTime ts(localTM);
-    return jsNontrivialString(exec, formatDate(ts) + " " + formatTime(ts, false));
+    GregorianDateTime ts(exec, localTM);
+    DateConversionBuffer date;
+    DateConversionBuffer time;
+    formatDate(ts, date);
+    formatTime(ts, time);
+    return jsNontrivialString(exec, makeString(date, " ", time));
 }
 
 CallType DateConstructor::getCallData(CallData& callData)
 }
 
 CallType DateConstructor::getCallData(CallData& callData)
@@ -148,12 +148,12 @@ CallType DateConstructor::getCallData(CallData& callData)
 
 static JSValue JSC_HOST_CALL dateParse(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 
 static JSValue JSC_HOST_CALL dateParse(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, parseDate(args.at(0).toString(exec)));
+    return jsNumber(exec, parseDate(exec, args.at(0).toString(exec)));
 }
 
 static JSValue JSC_HOST_CALL dateNow(ExecState* exec, JSObject*, JSValue, const ArgList&)
 {
 }
 
 static JSValue JSC_HOST_CALL dateNow(ExecState* exec, JSObject*, JSValue, const ArgList&)
 {
-    return jsNumber(exec, getCurrentUTCTime());
+    return jsNumber(exec, jsCurrentTime());
 }
 
 static JSValue JSC_HOST_CALL dateUTC(ExecState* exec, JSObject*, JSValue, const ArgList& args) 
 }
 
 static JSValue JSC_HOST_CALL dateUTC(ExecState* exec, JSObject*, JSValue, const ArgList& args) 
@@ -177,7 +177,7 @@ static JSValue JSC_HOST_CALL dateUTC(ExecState* exec, JSObject*, JSValue, const
     t.minute = args.at(4).toInt32(exec);
     t.second = args.at(5).toInt32(exec);
     double ms = (n >= 7) ? args.at(6).toNumber(exec) : 0;
     t.minute = args.at(4).toInt32(exec);
     t.second = args.at(5).toInt32(exec);
     double ms = (n >= 7) ? args.at(6).toNumber(exec) : 0;
-    return jsNumber(exec, gregorianDateTimeToMS(t, ms, true));
+    return jsNumber(exec, gregorianDateTimeToMS(exec, t, ms, true));
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index dcef3cc7f5e8ed13ffb5027726063cd86f20c70e..10e450e7cd2b59d2acc3b5526e03a0f8fc2d5906 100644 (file)
@@ -29,7 +29,7 @@ namespace JSC {
 
     class DateConstructor : public InternalFunction {
     public:
 
     class DateConstructor : public InternalFunction {
     public:
-        DateConstructor(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*);
+        DateConstructor(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
index a725478956dfd48c876e6a74d414037811ea31bb..f129407f7b1da41ba0b5ab46289dfe80ddee5935 100644 (file)
@@ -43,6 +43,7 @@
 #include "config.h"
 #include "DateConversion.h"
 
 #include "config.h"
 #include "DateConversion.h"
 
+#include "CallFrame.h"
 #include "UString.h"
 #include <wtf/DateMath.h>
 #include <wtf/StringExtras.h>
 #include "UString.h"
 #include <wtf/DateMath.h>
 #include <wtf/StringExtras.h>
@@ -51,51 +52,51 @@ using namespace WTF;
 
 namespace JSC {
 
 
 namespace JSC {
 
-double parseDate(const UString &date)
+double parseDate(ExecState* exec, const UString &date)
 {
 {
-    return parseDateFromNullTerminatedCharacters(date.UTF8String().c_str());
+    if (date == exec->globalData().cachedDateString)
+        return exec->globalData().cachedDateStringValue;
+    double value = parseDateFromNullTerminatedCharacters(exec, date.UTF8String().c_str());
+    exec->globalData().cachedDateString = date;
+    exec->globalData().cachedDateStringValue = value;
+    return value;
 }
 
 }
 
-UString formatDate(const GregorianDateTime &t)
+void formatDate(const GregorianDateTime &t, DateConversionBuffer& buffer)
 {
 {
-    char buffer[100];
-    snprintf(buffer, sizeof(buffer), "%s %s %02d %04d",
+    snprintf(buffer, DateConversionBufferSize, "%s %s %02d %04d",
         weekdayName[(t.weekDay + 6) % 7],
         monthName[t.month], t.monthDay, t.year + 1900);
         weekdayName[(t.weekDay + 6) % 7],
         monthName[t.month], t.monthDay, t.year + 1900);
-    return buffer;
 }
 
 }
 
-UString formatDateUTCVariant(const GregorianDateTime &t)
+void formatDateUTCVariant(const GregorianDateTime &t, DateConversionBuffer& buffer)
 {
 {
-    char buffer[100];
-    snprintf(buffer, sizeof(buffer), "%s, %02d %s %04d",
+    snprintf(buffer, DateConversionBufferSize, "%s, %02d %s %04d",
         weekdayName[(t.weekDay + 6) % 7],
         t.monthDay, monthName[t.month], t.year + 1900);
         weekdayName[(t.weekDay + 6) % 7],
         t.monthDay, monthName[t.month], t.year + 1900);
-    return buffer;
 }
 
 }
 
-UString formatTime(const GregorianDateTime &t, bool utc)
+void formatTime(const GregorianDateTime &t, DateConversionBuffer& buffer)
 {
 {
-    char buffer[100];
-    if (utc) {
-        snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", t.hour, t.minute, t.second);
-    } else {
-        int offset = abs(gmtoffset(t));
-        char timeZoneName[70];
-        struct tm gtm = t;
-        strftime(timeZoneName, sizeof(timeZoneName), "%Z", &gtm);
+    int offset = abs(gmtoffset(t));
+    char timeZoneName[70];
+    struct tm gtm = t;
+    strftime(timeZoneName, sizeof(timeZoneName), "%Z", &gtm);
 
 
-        if (timeZoneName[0]) {
-            snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d (%s)",
-                t.hour, t.minute, t.second,
-                gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, timeZoneName);
-        } else {
-            snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d",
-                t.hour, t.minute, t.second,
-                gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60);
-        }
+    if (timeZoneName[0]) {
+        snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT%c%02d%02d (%s)",
+            t.hour, t.minute, t.second,
+            gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, timeZoneName);
+    } else {
+        snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT%c%02d%02d",
+            t.hour, t.minute, t.second,
+            gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60);
     }
     }
-    return UString(buffer);
+}
+
+void formatTimeUTC(const GregorianDateTime &t, DateConversionBuffer& buffer)
+{
+    snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT", t.hour, t.minute, t.second);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 0d128158e93c27c257fcaabda1b3893276fd2737..ff32b503d852d814aa4bbeedbc120f625f2fdbd8 100644 (file)
 #ifndef DateConversion_h
 #define DateConversion_h
 
 #ifndef DateConversion_h
 #define DateConversion_h
 
-namespace WTF {
-    struct GregorianDateTime;
-}
+#include "UString.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-class UString;
+class ExecState;
+struct GregorianDateTime;
 
 
-double parseDate(const UString&);
-UString formatDate(const WTF::GregorianDateTime&);
-UString formatDateUTCVariant(const WTF::GregorianDateTime&);
-UString formatTime(const WTF::GregorianDateTime&, bool inputIsUTC);
+static const unsigned DateConversionBufferSize = 100;
+typedef char DateConversionBuffer[DateConversionBufferSize];
+
+double parseDate(ExecState* exec, const UString&);
+void formatDate(const GregorianDateTime&, DateConversionBuffer&);
+void formatDateUTCVariant(const GregorianDateTime&, DateConversionBuffer&);
+void formatTime(const GregorianDateTime&, DateConversionBuffer&);
+void formatTimeUTC(const GregorianDateTime&, DateConversionBuffer&);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index 62791aecb28627f6f7b0668b5f128e18da04f505..b43b183e27ea3974066e1e2d3fab74d16e84d55c 100644 (file)
@@ -22,6 +22,8 @@
 #include "config.h"
 #include "DateInstance.h"
 
 #include "config.h"
 #include "DateInstance.h"
 
+#include "JSGlobalObject.h"
+
 #include <math.h>
 #include <wtf/DateMath.h>
 #include <wtf/MathExtras.h>
 #include <math.h>
 #include <wtf/DateMath.h>
 #include <wtf/MathExtras.h>
@@ -30,89 +32,56 @@ using namespace WTF;
 
 namespace JSC {
 
 
 namespace JSC {
 
-struct DateInstance::Cache {
-    double m_gregorianDateTimeCachedForMS;
-    GregorianDateTime m_cachedGregorianDateTime;
-    double m_gregorianDateTimeUTCCachedForMS;
-    GregorianDateTime m_cachedGregorianDateTimeUTC;
-};
-
 const ClassInfo DateInstance::info = {"Date", 0, 0, 0};
 
 const ClassInfo DateInstance::info = {"Date", 0, 0, 0};
 
-DateInstance::DateInstance(PassRefPtr<Structure> structure)
+DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure)
     : JSWrapperObject(structure)
     : JSWrapperObject(structure)
-    , m_cache(0)
 {
 {
+    setInternalValue(jsNaN(exec));
 }
 
 }
 
-DateInstance::~DateInstance()
+DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure, double time)
+    : JSWrapperObject(structure)
 {
 {
-    delete m_cache;
+    setInternalValue(jsNumber(exec, timeClip(time)));
 }
 
 }
 
-void DateInstance::msToGregorianDateTime(double milli, bool outputIsUTC, GregorianDateTime& t) const
+DateInstance::DateInstance(ExecState* exec, double time)
+    : JSWrapperObject(exec->lexicalGlobalObject()->dateStructure())
 {
 {
-    if (!m_cache) {
-        m_cache = new Cache;
-        m_cache->m_gregorianDateTimeCachedForMS = NaN;
-        m_cache->m_gregorianDateTimeUTCCachedForMS = NaN;
-    }
-
-    if (outputIsUTC) {
-        if (m_cache->m_gregorianDateTimeUTCCachedForMS != milli) {
-            WTF::msToGregorianDateTime(milli, true, m_cache->m_cachedGregorianDateTimeUTC);
-            m_cache->m_gregorianDateTimeUTCCachedForMS = milli;
-        }
-        t.copyFrom(m_cache->m_cachedGregorianDateTimeUTC);
-    } else {
-        if (m_cache->m_gregorianDateTimeCachedForMS != milli) {
-            WTF::msToGregorianDateTime(milli, false, m_cache->m_cachedGregorianDateTime);
-            m_cache->m_gregorianDateTimeCachedForMS = milli;
-        }
-        t.copyFrom(m_cache->m_cachedGregorianDateTime);
-    }
+    setInternalValue(jsNumber(exec, timeClip(time)));
 }
 
 }
 
-bool DateInstance::getTime(GregorianDateTime& t, int& offset) const
+const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exec) const
 {
     double milli = internalNumber();
     if (isnan(milli))
 {
     double milli = internalNumber();
     if (isnan(milli))
-        return false;
-    
-    msToGregorianDateTime(milli, false, t);
-    offset = gmtoffset(t);
-    return true;
+        return 0;
+
+    if (!m_data)
+        m_data = exec->globalData().dateInstanceCache.add(milli);
+
+    if (m_data->m_gregorianDateTimeCachedForMS != milli) {
+        msToGregorianDateTime(exec, milli, false, m_data->m_cachedGregorianDateTime);
+        m_data->m_gregorianDateTimeCachedForMS = milli;
+    }
+    return &m_data->m_cachedGregorianDateTime;
 }
 
 }
 
-bool DateInstance::getUTCTime(GregorianDateTime& t) const
+const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(ExecState* exec) const
 {
     double milli = internalNumber();
     if (isnan(milli))
 {
     double milli = internalNumber();
     if (isnan(milli))
-        return false;
-    
-    msToGregorianDateTime(milli, true, t);
-    return true;
-}
+        return 0;
 
 
-bool DateInstance::getTime(double& milli, int& offset) const
-{
-    milli = internalNumber();
-    if (isnan(milli))
-        return false;
-    
-    GregorianDateTime t;
-    msToGregorianDateTime(milli, false, t);
-    offset = gmtoffset(t);
-    return true;
-}
+    if (!m_data)
+        m_data = exec->globalData().dateInstanceCache.add(milli);
 
 
-bool DateInstance::getUTCTime(double& milli) const
-{
-    milli = internalNumber();
-    if (isnan(milli))
-        return false;
-    
-    return true;
+    if (m_data->m_gregorianDateTimeUTCCachedForMS != milli) {
+        msToGregorianDateTime(exec, milli, true, m_data->m_cachedGregorianDateTimeUTC);
+        m_data->m_gregorianDateTimeUTCCachedForMS = milli;
+    }
+    return &m_data->m_cachedGregorianDateTimeUTC;
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 3b73521a7cfc5cddf8b4ab18acec2eeed9373edd..77d46de5df7d5e155e7e513359e38e02f149a0df 100644 (file)
@@ -31,27 +31,42 @@ namespace JSC {
 
     class DateInstance : public JSWrapperObject {
     public:
 
     class DateInstance : public JSWrapperObject {
     public:
-        explicit DateInstance(PassRefPtr<Structure>);
-        virtual ~DateInstance();
+        DateInstance(ExecState*, double);
+        DateInstance(ExecState*, NonNullPassRefPtr<Structure>, double);
+        explicit DateInstance(ExecState*, NonNullPassRefPtr<Structure>);
 
         double internalNumber() const { return internalValue().uncheckedGetNumber(); }
 
 
         double internalNumber() const { return internalValue().uncheckedGetNumber(); }
 
-        bool getTime(WTF::GregorianDateTime&, int& offset) const;
-        bool getUTCTime(WTF::GregorianDateTime&) const;
-        bool getTime(double& milliseconds, int& offset) const;
-        bool getUTCTime(double& milliseconds) const;
-
-        static const ClassInfo info;
-
-        void msToGregorianDateTime(double, bool outputIsUTC, WTF::GregorianDateTime&) const;
+        static JS_EXPORTDATA const ClassInfo info;
+
+        const GregorianDateTime* gregorianDateTime(ExecState* exec) const
+        {
+            if (m_data && m_data->m_gregorianDateTimeCachedForMS == internalNumber())
+                return &m_data->m_cachedGregorianDateTime;
+            return calculateGregorianDateTime(exec);
+        }
+        
+        const GregorianDateTime* gregorianDateTimeUTC(ExecState* exec) const
+        {
+            if (m_data && m_data->m_gregorianDateTimeUTCCachedForMS == internalNumber())
+                return &m_data->m_cachedGregorianDateTimeUTC;
+            return calculateGregorianDateTimeUTC(exec);
+        }
+
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+        }
+
+    protected:
+        static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags;
 
     private:
 
     private:
+        const GregorianDateTime* calculateGregorianDateTime(ExecState*) const;
+        const GregorianDateTime* calculateGregorianDateTimeUTC(ExecState*) const;
         virtual const ClassInfo* classInfo() const { return &info; }
 
         virtual const ClassInfo* classInfo() const { return &info; }
 
-        using JSWrapperObject::internalValue;
-
-        struct Cache;
-        mutable Cache* m_cache;
+        mutable RefPtr<DateInstanceData> m_data;
     };
 
     DateInstance* asDateInstance(JSValue);
     };
 
     DateInstance* asDateInstance(JSValue);
diff --git a/runtime/DateInstanceCache.h b/runtime/DateInstanceCache.h
new file mode 100644 (file)
index 0000000..d208580
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DateInstanceCache_h
+#define DateInstanceCache_h
+
+#include <wtf/DateMath.h>
+#include <wtf/HashFunctions.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace JSC {
+
+    extern const double NaN;
+
+    class DateInstanceData : public RefCounted<DateInstanceData> {
+    public:
+        static PassRefPtr<DateInstanceData> create() { return adoptRef(new DateInstanceData); }
+
+        double m_gregorianDateTimeCachedForMS;
+        GregorianDateTime m_cachedGregorianDateTime;
+        double m_gregorianDateTimeUTCCachedForMS;
+        GregorianDateTime m_cachedGregorianDateTimeUTC;
+
+    private:
+        DateInstanceData()
+            : m_gregorianDateTimeCachedForMS(NaN)
+            , m_gregorianDateTimeUTCCachedForMS(NaN)
+        {
+        }
+    };
+
+    class DateInstanceCache {
+    public:
+        DateInstanceCache()
+        {
+            reset();
+        }
+        
+        void reset()
+        {
+            for (size_t i = 0; i < cacheSize; ++i)
+                m_cache[i].key = NaN;
+        }
+        
+        DateInstanceData* add(double d)
+        {
+            CacheEntry& entry = lookup(d);
+            if (d == entry.key)
+                return entry.value.get();
+
+            entry.key = d;
+            entry.value = DateInstanceData::create();
+            return entry.value.get();
+        }
+
+    private:
+        static const size_t cacheSize = 16;
+
+        struct CacheEntry {
+            double key;
+            RefPtr<DateInstanceData> value;
+        };
+
+        CacheEntry& lookup(double d) { return m_cache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; }
+
+        CacheEntry m_cache[cacheSize];
+    };
+
+} // namespace JSC
+
+#endif // DateInstanceCache_h
index ce7df28c35832210762a59b47b817b9bd7117196..c0df7e96cfbc712ead62a764f96bbad83278dbc9 100644 (file)
@@ -28,7 +28,6 @@
 #include "JSString.h"
 #include "ObjectPrototype.h"
 #include "DateInstance.h"
 #include "JSString.h"
 #include "ObjectPrototype.h"
 #include "DateInstance.h"
-#include <float.h>
 
 #if !PLATFORM(MAC) && HAVE(LANGINFO_H)
 #include <langinfo.h>
 
 #if !PLATFORM(MAC) && HAVE(LANGINFO_H)
 #include <langinfo.h>
@@ -58,7 +57,7 @@
 
 #include <CoreFoundation/CoreFoundation.h>
 
 
 #include <CoreFoundation/CoreFoundation.h>
 
-#if PLATFORM(WINCE) && !PLATFORM(QT)
+#if OS(WINCE) && !PLATFORM(QT)
 extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t); //provided by libce
 #endif
 
 extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t); //provided by libce
 #endif
 
@@ -324,10 +323,9 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState
 
 // ECMA 15.9.4
 
 
 // ECMA 15.9.4
 
-DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<Structure> structure)
-    : DateInstance(structure)
+DatePrototype::DatePrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
+    : DateInstance(exec, structure)
 {
 {
-    setInternalValue(jsNaN(exec));
     // The constructor will be added later, after DateConstructor has been built.
 }
 
     // The constructor will be added later, after DateConstructor has been built.
 }
 
@@ -336,408 +334,333 @@ bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& proper
     return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
 }
 
     return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
 }
 
+
+bool DatePrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, descriptor);
+}
+
 // Functions
 
 JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 // Functions
 
 JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNontrivialString(exec, "Invalid Date");
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc));
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNontrivialString(exec, "Invalid Date");
+    DateConversionBuffer date;
+    DateConversionBuffer time;
+    formatDate(*gregorianDateTime, date);
+    formatTime(*gregorianDateTime, time);
+    return jsNontrivialString(exec, makeString(date, " ", time));
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = true;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNontrivialString(exec, "Invalid Date");
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
+    if (!gregorianDateTime)
+        return jsNontrivialString(exec, "Invalid Date");
+    DateConversionBuffer date;
+    DateConversionBuffer time;
+    formatDateUTCVariant(*gregorianDateTime, date);
+    formatTimeUTC(*gregorianDateTime, time);
+    return jsNontrivialString(exec, makeString(date, " ", time));
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
     
         return throwError(exec, TypeError);
     
-    const bool utc = true;
-    
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (!isfinite(milli))
-        return jsNontrivialString(exec, "Invalid Date");
     
     
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second)
-    // 6 for formatting and one for null termination = 23.  We add one extra character to allow us to force null termination.
-    char buffer[24];
-    snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02dZ", 1900 + t.year, t.month + 1, t.monthDay, t.hour, t.minute, t.second);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
+    if (!gregorianDateTime)
+        return jsNontrivialString(exec, "Invalid Date");
+    // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds)
+    // 6 for formatting and one for null termination = 27.  We add one extra character to allow us to force null termination.
+    char buffer[28];
+    snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, static_cast<int>(fmod(thisDateObj->internalNumber(), 1000)));
     buffer[sizeof(buffer) - 1] = 0;
     return jsNontrivialString(exec, buffer);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     buffer[sizeof(buffer) - 1] = 0;
     return jsNontrivialString(exec, buffer);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNontrivialString(exec, "Invalid Date");
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNontrivialString(exec, formatDate(t));
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNontrivialString(exec, "Invalid Date");
+    DateConversionBuffer date;
+    formatDate(*gregorianDateTime, date);
+    return jsNontrivialString(exec, date);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNontrivialString(exec, "Invalid Date");
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNontrivialString(exec, formatTime(t, utc));
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNontrivialString(exec, "Invalid Date");
+    DateConversionBuffer time;
+    formatTime(*gregorianDateTime, time);
+    return jsNontrivialString(exec, time);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNontrivialString(exec, "Invalid Date");
-
-    return formatLocaleDate(exec, thisDateObj, milli, LocaleDateAndTime, args);
+    return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDateAndTime, args);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNontrivialString(exec, "Invalid Date");
-
-    return formatLocaleDate(exec, thisDateObj, milli, LocaleDate, args);
+    return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDate, args);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNontrivialString(exec, "Invalid Date");
-
-    return formatLocaleDate(exec, thisDateObj, milli, LocaleTime, args);
+    return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleTime, args);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
-
-    return jsNumber(exec, milli);
+    return asDateInstance(thisValue)->internalValue(); 
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, 1900 + t.year);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, 1900 + gregorianDateTime->year);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = true;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, 1900 + t.year);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, 1900 + gregorianDateTime->year);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = true;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNontrivialString(exec, "Invalid Date");
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
+    if (!gregorianDateTime)
+        return jsNontrivialString(exec, "Invalid Date");
+    DateConversionBuffer date;
+    DateConversionBuffer time;
+    formatDateUTCVariant(*gregorianDateTime, date);
+    formatTimeUTC(*gregorianDateTime, time);
+    return jsNontrivialString(exec, makeString(date, " ", time));
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.month);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->month);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = true;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.month);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->month);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.monthDay);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->monthDay);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = true;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.monthDay);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->monthDay);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.weekDay);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->weekDay);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = true;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.weekDay);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->weekDay);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.hour);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->hour);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = true;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.hour);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->hour);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.minute);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->minute);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = true;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.minute);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->minute);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.second);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->second);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = true;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, t.second);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, gregorianDateTime->second);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
@@ -752,7 +675,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, J
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 
 JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
@@ -767,24 +690,20 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*
 
 JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 
 JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
-    return jsNumber(exec, -gmtoffset(t) / minutesPerHour);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
+    return jsNumber(exec, -gregorianDateTime->utcOffset / minutesPerHour);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
@@ -797,7 +716,7 @@ JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue t
 
 static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
 {
 
 static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue);
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -812,23 +731,28 @@ static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const
     double secs = floor(milli / msPerSecond);
     double ms = milli - secs * msPerSecond;
 
     double secs = floor(milli / msPerSecond);
     double ms = milli - secs * msPerSecond;
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
+    const GregorianDateTime* other = inputIsUTC 
+        ? thisDateObj->gregorianDateTimeUTC(exec)
+        : thisDateObj->gregorianDateTime(exec);
+    if (!other)
+        return jsNaN(exec);
 
 
-    if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
+    GregorianDateTime gregorianDateTime;
+    gregorianDateTime.copyFrom(*other);
+    if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &gregorianDateTime)) {
         JSValue result = jsNaN(exec);
         thisDateObj->setInternalValue(result);
         return result;
     } 
     
         JSValue result = jsNaN(exec);
         thisDateObj->setInternalValue(result);
         return result;
     } 
     
-    JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
+    JSValue result = jsNumber(exec, gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
     thisDateObj->setInternalValue(result);
     return result;
 }
 
 static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
 {
     thisDateObj->setInternalValue(result);
     return result;
 }
 
 static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue);
         return throwError(exec, TypeError);
 
     DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -839,26 +763,28 @@ static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const
     }      
     
     double milli = thisDateObj->internalNumber();
     }      
     
     double milli = thisDateObj->internalNumber();
-    double ms = 0;
-
-    GregorianDateTime t;
-    if (numArgsToUse == 3 && isnan(milli))
-        // Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear)
-        // the time must be reset to +0 if it is NaN. 
-        thisDateObj->msToGregorianDateTime(0, true, t);
-    else {
-        double secs = floor(milli / msPerSecond);
-        ms = milli - secs * msPerSecond;
-        thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
+    double ms = 0; 
+
+    GregorianDateTime gregorianDateTime; 
+    if (numArgsToUse == 3 && isnan(milli)) 
+        msToGregorianDateTime(exec, 0, true, gregorianDateTime); 
+    else { 
+        ms = milli - floor(milli / msPerSecond) * msPerSecond; 
+        const GregorianDateTime* other = inputIsUTC 
+            ? thisDateObj->gregorianDateTimeUTC(exec)
+            : thisDateObj->gregorianDateTime(exec);
+        if (!other)
+            return jsNaN(exec);
+        gregorianDateTime.copyFrom(*other);
     }
     
     }
     
-    if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
+    if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &gregorianDateTime)) {
         JSValue result = jsNaN(exec);
         thisDateObj->setInternalValue(result);
         return result;
     } 
            
         JSValue result = jsNaN(exec);
         thisDateObj->setInternalValue(result);
         return result;
     } 
            
-    JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
+    JSValue result = jsNumber(exec, gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
     thisDateObj->setInternalValue(result);
     return result;
 }
     thisDateObj->setInternalValue(result);
     return result;
 }
@@ -949,11 +875,9 @@ JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JS
 
 JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
 
 JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue);     
     if (args.isEmpty()) { 
         JSValue result = jsNaN(exec);
     DateInstance* thisDateObj = asDateInstance(thisValue);     
     if (args.isEmpty()) { 
         JSValue result = jsNaN(exec);
@@ -964,15 +888,16 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t
     double milli = thisDateObj->internalNumber();
     double ms = 0;
 
     double milli = thisDateObj->internalNumber();
     double ms = 0;
 
-    GregorianDateTime t;
+    GregorianDateTime gregorianDateTime;
     if (isnan(milli))
         // Based on ECMA 262 B.2.5 (setYear)
         // the time must be reset to +0 if it is NaN. 
     if (isnan(milli))
         // Based on ECMA 262 B.2.5 (setYear)
         // the time must be reset to +0 if it is NaN. 
-        thisDateObj->msToGregorianDateTime(0, true, t);
+        msToGregorianDateTime(exec, 0, true, gregorianDateTime);
     else {   
         double secs = floor(milli / msPerSecond);
         ms = milli - secs * msPerSecond;
     else {   
         double secs = floor(milli / msPerSecond);
         ms = milli - secs * msPerSecond;
-        thisDateObj->msToGregorianDateTime(milli, utc, t);
+        if (const GregorianDateTime* other = thisDateObj->gregorianDateTime(exec))
+            gregorianDateTime.copyFrom(*other);
     }
     
     bool ok = true;
     }
     
     bool ok = true;
@@ -983,29 +908,25 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t
         return result;
     }
             
         return result;
     }
             
-    t.year = (year > 99 || year < 0) ? year - 1900 : year;
-    JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc));
+    gregorianDateTime.year = (year > 99 || year < 0) ? year - 1900 : year;
+    JSValue result = jsNumber(exec, gregorianDateTimeToMS(exec, gregorianDateTime, ms, false));
     thisDateObj->setInternalValue(result);
     return result;
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     thisDateObj->setInternalValue(result);
     return result;
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&DateInstance::info))
+    if (!thisValue.inherits(&DateInstance::info))
         return throwError(exec, TypeError);
 
         return throwError(exec, TypeError);
 
-    const bool utc = false;
-
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    double milli = thisDateObj->internalNumber();
-    if (isnan(milli))
-        return jsNaN(exec);
 
 
-    GregorianDateTime t;
-    thisDateObj->msToGregorianDateTime(milli, utc, t);
+    const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
+    if (!gregorianDateTime)
+        return jsNaN(exec);
 
     // NOTE: IE returns the full year even in getYear.
 
     // NOTE: IE returns the full year even in getYear.
-    return jsNumber(exec, t.year);
+    return jsNumber(exec, gregorianDateTime->year);
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 }
 
 JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
index 5f4d0ec43da2cda5fcb46235d46997dd3b706933..612ca06a4e9ca871906c3646bab6b44d26a2a9ab 100644 (file)
@@ -29,17 +29,22 @@ namespace JSC {
 
     class DatePrototype : public DateInstance {
     public:
 
     class DatePrototype : public DateInstance {
     public:
-        DatePrototype(ExecState*, PassRefPtr<Structure>);
+        DatePrototype(ExecState*, NonNullPassRefPtr<Structure>);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType));
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
         }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | DateInstance::StructureFlags;
+
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index db1d8ccb0b60a26c44da665cf13efa2bcdc0f322..ddd4bc4f5e1398ab60626d0ee06623b3cecdbc4c 100644 (file)
@@ -97,6 +97,12 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const char* message)
     return create(exec, type, message, -1, -1, NULL);
 }
 
     return create(exec, type, message, -1, -1, NULL);
 }
 
+JSObject* throwError(ExecState* exec, JSObject* error)
+{
+    exec->setException(error);
+    return error;
+}
+
 JSObject* throwError(ExecState* exec, ErrorType type)
 {
     JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL);
 JSObject* throwError(ExecState* exec, ErrorType type)
 {
     JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL);
index adf7fdf9e14a291bf0bf40fa017b59a1e6319a8c..e959cff6a573b2cd5bfd79fbd8fec99bfda7a3ab 100644 (file)
@@ -59,6 +59,7 @@ namespace JSC {
     JSObject* throwError(ExecState*, ErrorType, const UString& message);
     JSObject* throwError(ExecState*, ErrorType, const char* message);
     JSObject* throwError(ExecState*, ErrorType);
     JSObject* throwError(ExecState*, ErrorType, const UString& message);
     JSObject* throwError(ExecState*, ErrorType, const char* message);
     JSObject* throwError(ExecState*, ErrorType);
+    JSObject* throwError(ExecState*, JSObject*);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index 07b7e233814977111018ec8cb95e7b48993e9e6b..b9c3f586c298e4bb6af60ba0c24cf237c6241e61 100644 (file)
@@ -29,7 +29,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
 
 
 ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
 
-ErrorConstructor::ErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, ErrorPrototype* errorPrototype)
+ErrorConstructor::ErrorConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ErrorPrototype* errorPrototype)
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, errorPrototype->classInfo()->className))
 {
     // ECMA 15.11.3.1 Error.prototype
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, errorPrototype->classInfo()->className))
 {
     // ECMA 15.11.3.1 Error.prototype
index 2dd41244b1b19b7d3b02c68244f974529c3643d0..e3d789b0d60864544ef5b4029fdf9418f06a452c 100644 (file)
@@ -30,7 +30,7 @@ namespace JSC {
 
     class ErrorConstructor : public InternalFunction {
     public:
 
     class ErrorConstructor : public InternalFunction {
     public:
-        ErrorConstructor(ExecState*, PassRefPtr<Structure>, ErrorPrototype*);
+        ErrorConstructor(ExecState*, NonNullPassRefPtr<Structure>, ErrorPrototype*);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
index 2e2cdce9360d396552db898f0ca68821e59142e3..1cdb87a5a9169c925ffc67e4b47efa50184351aa 100644 (file)
@@ -25,7 +25,7 @@ namespace JSC {
 
 const ClassInfo ErrorInstance::info = { "Error", 0, 0, 0 };
 
 
 const ClassInfo ErrorInstance::info = { "Error", 0, 0, 0 };
 
-ErrorInstance::ErrorInstance(PassRefPtr<Structure> structure)
+ErrorInstance::ErrorInstance(NonNullPassRefPtr<Structure> structure)
     : JSObject(structure)
 {
 }
     : JSObject(structure)
 {
 }
index 6f9d262ea72364c6f5375de0264c9ce9caed494d..9f53b5154a345d923a430a944ee901a5e23d33bf 100644 (file)
@@ -27,7 +27,7 @@ namespace JSC {
 
     class ErrorInstance : public JSObject {
     public:
 
     class ErrorInstance : public JSObject {
     public:
-        explicit ErrorInstance(PassRefPtr<Structure>);
+        explicit ErrorInstance(NonNullPassRefPtr<Structure>);
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
index 599390ee92f280c564786993d52e4e7ac0065cf8..be9e4b8a120fb17ea3cb117534d07a5272bb4b2e 100644 (file)
@@ -34,7 +34,7 @@ ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
 static JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
 
 // ECMA 15.9.4
 static JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
 
 // ECMA 15.9.4
-ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+ErrorPrototype::ErrorPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
     : ErrorInstance(structure)
 {
     // The constructor will be added later in ErrorConstructor's constructor
     : ErrorInstance(structure)
 {
     // The constructor will be added later in ErrorConstructor's constructor
@@ -48,21 +48,19 @@ ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure,
 JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     JSObject* thisObj = thisValue.toThisObject(exec);
 JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     JSObject* thisObj = thisValue.toThisObject(exec);
+    JSValue name = thisObj->get(exec, exec->propertyNames().name);
+    JSValue message = thisObj->get(exec, exec->propertyNames().message);
 
 
-    UString s = "Error";
+    // Mozilla-compatible format.
 
 
-    JSValue v = thisObj->get(exec, exec->propertyNames().name);
-    if (!v.isUndefined())
-        s = v.toString(exec);
-
-    v = thisObj->get(exec, exec->propertyNames().message);
-    if (!v.isUndefined()) {
-        // Mozilla-compatible format.
-        s += ": ";
-        s += v.toString(exec);
+    if (!name.isUndefined()) {
+        if (!message.isUndefined())
+            return jsNontrivialString(exec, makeString(name.toString(exec), ": ", message.toString(exec)));
+        return jsNontrivialString(exec, name.toString(exec));
     }
     }
-
-    return jsNontrivialString(exec, s);
+    if (!message.isUndefined())
+        return jsNontrivialString(exec, makeString("Error: ", message.toString(exec)));
+    return jsNontrivialString(exec, "Error");
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 53d12d918b2f8e80772664a1e150c429108b5bbc..a5615902d30142b953a8af2275162cd6ea957747 100644 (file)
@@ -29,7 +29,7 @@ namespace JSC {
 
     class ErrorPrototype : public ErrorInstance {
     public:
 
     class ErrorPrototype : public ErrorInstance {
     public:
-        ErrorPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+        ErrorPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index e63594c032ca5436d5912b31aeb6dbc35a5365d3..9bb740e309c6f70cbeb01b17669dbbf2078ffba6 100644 (file)
@@ -66,15 +66,18 @@ JSValue createStackOverflowError(ExecState* exec)
     return createError(exec, RangeError, "Maximum call stack size exceeded.");
 }
 
     return createError(exec, RangeError, "Maximum call stack size exceeded.");
 }
 
+JSValue createTypeError(ExecState* exec, const char* message)
+{
+    return createError(exec, TypeError, message);
+}
+
 JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock)
 {
     int startOffset = 0;
     int endOffset = 0;
     int divotPoint = 0;
     int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
 JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock)
 {
     int startOffset = 0;
     int endOffset = 0;
     int divotPoint = 0;
     int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
-    UString message = "Can't find variable: ";
-    message.append(ident.ustring());
-    JSObject* exception = Error::create(exec, ReferenceError, message, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+    JSObject* exception = Error::create(exec, ReferenceError, makeString("Can't find variable: ", ident.ustring()), line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
@@ -83,60 +86,37 @@ JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, u
     
 static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue value, UString error)
 {
     
 static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue value, UString error)
 {
-    if (!expressionStop || expressionStart > codeBlock->source()->length()) {
-        UString errorText = value.toString(exec);
-        errorText.append(" is ");
-        errorText.append(error);
-        return errorText;
-    }
+    if (!expressionStop || expressionStart > codeBlock->source()->length())
+        return makeString(value.toString(exec), " is ", error);
+    if (expressionStart < expressionStop)
+        return makeString("Result of expression '", codeBlock->source()->getRange(expressionStart, expressionStop), "' [", value.toString(exec), "] is ", error, ".");
 
 
-    UString errorText = "Result of expression ";
-    
-    if (expressionStart < expressionStop) {
-        errorText.append('\'');
-        errorText.append(codeBlock->source()->getRange(expressionStart, expressionStop));
-        errorText.append("' [");
-        errorText.append(value.toString(exec));
-        errorText.append("] is ");
-    } else {
-        // No range information, so give a few characters of context
-        const UChar* data = codeBlock->source()->data();
-        int dataLength = codeBlock->source()->length();
-        int start = expressionStart;
-        int stop = expressionStart;
-        // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
-        // then strip whitespace.
-        while (start > 0 && (expressionStart - start < 20) && data[start - 1] != '\n')
-            start--;
-        while (start < (expressionStart - 1) && isStrWhiteSpace(data[start]))
-            start++;
-        while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n')
-            stop++;
-        while (stop > expressionStart && isStrWhiteSpace(data[stop]))
-            stop--;
-        errorText.append("near '...");
-        errorText.append(codeBlock->source()->getRange(start, stop));
-        errorText.append("...' [");
-        errorText.append(value.toString(exec));
-        errorText.append("] is ");
-    }
-    errorText.append(error);
-    errorText.append(".");
-    return errorText;
+    // No range information, so give a few characters of context
+    const UChar* data = codeBlock->source()->data();
+    int dataLength = codeBlock->source()->length();
+    int start = expressionStart;
+    int stop = expressionStart;
+    // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
+    // then strip whitespace.
+    while (start > 0 && (expressionStart - start < 20) && data[start - 1] != '\n')
+        start--;
+    while (start < (expressionStart - 1) && isStrWhiteSpace(data[start]))
+        start++;
+    while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n')
+        stop++;
+    while (stop > expressionStart && isStrWhiteSpace(data[stop]))
+        stop--;
+    return makeString("Result of expression near '...", codeBlock->source()->getRange(start, stop), "...' [", value.toString(exec), "] is ", error, ".");
 }
 
 JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock)
 {
 }
 
 JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock)
 {
-    UString message = "not a valid argument for '";
-    message.append(op);
-    message.append("'");
-    
     int startOffset = 0;
     int endOffset = 0;
     int divotPoint = 0;
     int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
     int startOffset = 0;
     int endOffset = 0;
     int divotPoint = 0;
     int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
-    UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, message);
-    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+    UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, makeString("not a valid argument for '", op, "'"));
+    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
@@ -157,7 +137,7 @@ JSObject* createNotAConstructorError(ExecState* exec, JSValue value, unsigned by
         startPoint++;
     
     UString errorMessage = createErrorMessage(exec, codeBlock, line, startPoint, divotPoint, value, "not a constructor");
         startPoint++;
     
     UString errorMessage = createErrorMessage(exec, codeBlock, line, startPoint, divotPoint, value, "not a constructor");
-    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
@@ -171,7 +151,7 @@ JSValue createNotAFunctionError(ExecState* exec, JSValue value, unsigned bytecod
     int divotPoint = 0;
     int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
     UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, value, "not a function");
     int divotPoint = 0;
     int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
     UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, value, "not a function");
-    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());    
+    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());    
     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
@@ -201,7 +181,7 @@ JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error,
     int divotPoint = 0;
     int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
     UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, error->isNull() ? jsNull() : jsUndefined(), "not an object");
     int divotPoint = 0;
     int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
     UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, error->isNull() ? jsNull() : jsUndefined(), "not an object");
-    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
index 93629dc5991a33a20d217b8164c799e842a4859c..e739d0954c7b0c73d1e78a4f0eba840bf3e0dae7 100644 (file)
@@ -35,15 +35,16 @@ namespace JSC {
     class CodeBlock;
     class ExecState;
     class Identifier;
     class CodeBlock;
     class ExecState;
     class Identifier;
-    class Instruction;
     class JSGlobalData;
     class JSNotAnObjectErrorStub;
     class JSObject;
     class JSValue;
     class Node;
     class JSGlobalData;
     class JSNotAnObjectErrorStub;
     class JSObject;
     class JSValue;
     class Node;
-
+    struct Instruction;
+    
     JSValue createInterruptedExecutionException(JSGlobalData*);
     JSValue createStackOverflowError(ExecState*);
     JSValue createInterruptedExecutionException(JSGlobalData*);
     JSValue createStackOverflowError(ExecState*);
+    JSValue createTypeError(ExecState*, const char* message);
     JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*);
     JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull);
     JSObject* createInvalidParamError(ExecState*, const char* op, JSValue, unsigned bytecodeOffset, CodeBlock*);
     JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*);
     JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull);
     JSObject* createInvalidParamError(ExecState*, const char* op, JSValue, unsigned bytecodeOffset, CodeBlock*);
diff --git a/runtime/Executable.cpp b/runtime/Executable.cpp
new file mode 100644 (file)
index 0000000..bc18cc9
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "Executable.h"
+
+#include "BytecodeGenerator.h"
+#include "CodeBlock.h"
+#include "JIT.h"
+#include "Parser.h"
+#include "StringBuilder.h"
+#include "Vector.h"
+
+namespace JSC {
+
+#if ENABLE(JIT)
+NativeExecutable::~NativeExecutable()
+{
+}
+#endif
+
+VPtrHackExecutable::~VPtrHackExecutable()
+{
+}
+
+EvalExecutable::~EvalExecutable()
+{
+    delete m_evalCodeBlock;
+}
+
+ProgramExecutable::~ProgramExecutable()
+{
+    delete m_programCodeBlock;
+}
+
+FunctionExecutable::~FunctionExecutable()
+{
+    delete m_codeBlock;
+}
+
+JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    int errLine;
+    UString errMsg;
+    RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
+    if (!evalNode)
+        return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
+    recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine());
+
+    ScopeChain scopeChain(scopeChainNode);
+    JSGlobalObject* globalObject = scopeChain.globalObject();
+
+    ASSERT(!m_evalCodeBlock);
+    m_evalCodeBlock = new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth());
+    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock));
+    generator->generate();
+    
+    evalNode->destroyData();
+    return 0;
+}
+
+JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
+{
+    int errLine;
+    UString errMsg;
+    RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
+    if (!programNode)
+        return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
+    return 0;
+}
+
+JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    int errLine;
+    UString errMsg;
+    RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
+    if (!programNode)
+        return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
+    recordParse(programNode->features(), programNode->lineNo(), programNode->lastLine());
+
+    ScopeChain scopeChain(scopeChainNode);
+    JSGlobalObject* globalObject = scopeChain.globalObject();
+    
+    ASSERT(!m_programCodeBlock);
+    m_programCodeBlock = new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider());
+    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(programNode.get(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock));
+    generator->generate();
+
+    programNode->destroyData();
+    return 0;
+}
+
+void FunctionExecutable::compile(ExecState*, ScopeChainNode* scopeChainNode)
+{
+    JSGlobalData* globalData = scopeChainNode->globalData;
+    RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+    if (m_forceUsesArguments)
+        body->setUsesArguments();
+    body->finishParsing(m_parameters, m_name);
+    recordParse(body->features(), body->lineNo(), body->lastLine());
+
+    ScopeChain scopeChain(scopeChainNode);
+    JSGlobalObject* globalObject = scopeChain.globalObject();
+
+    ASSERT(!m_codeBlock);
+    m_codeBlock = new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset());
+    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlock->symbolTable(), m_codeBlock));
+    generator->generate();
+    m_numParameters = m_codeBlock->m_numParameters;
+    ASSERT(m_numParameters);
+    m_numVariables = m_codeBlock->m_numVars;
+
+    body->destroyData();
+}
+
+#if ENABLE(JIT)
+
+void EvalExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
+    m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
+
+#if !ENABLE(OPCODE_SAMPLING)
+    if (!BytecodeGenerator::dumpsGeneratedCode())
+        codeBlock->discardBytecode();
+#endif
+}
+
+void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
+    m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
+
+#if !ENABLE(OPCODE_SAMPLING)
+    if (!BytecodeGenerator::dumpsGeneratedCode())
+        codeBlock->discardBytecode();
+#endif
+}
+
+void FunctionExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
+    m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
+
+#if !ENABLE(OPCODE_SAMPLING)
+    if (!BytecodeGenerator::dumpsGeneratedCode())
+        codeBlock->discardBytecode();
+#endif
+}
+
+#endif
+
+void FunctionExecutable::markAggregate(MarkStack& markStack)
+{
+    if (m_codeBlock)
+        m_codeBlock->markAggregate(markStack);
+}
+
+ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
+{
+    RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+    if (m_forceUsesArguments)
+        newFunctionBody->setUsesArguments();
+    newFunctionBody->finishParsing(m_parameters, m_name);
+
+    ScopeChain scopeChain(scopeChainNode);
+    JSGlobalObject* globalObject = scopeChain.globalObject();
+
+    OwnPtr<CodeBlock> newCodeBlock(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
+    globalData->functionCodeBlockBeingReparsed = newCodeBlock.get();
+
+    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(newFunctionBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get()));
+    generator->setRegeneratingForExceptionInfo(static_cast<FunctionCodeBlock*>(codeBlock));
+    generator->generate();
+
+    ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
+
+#if ENABLE(JIT)
+    JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
+    ASSERT(newJITCode.size() == generatedJITCode().size());
+#endif
+
+    globalData->functionCodeBlockBeingReparsed = 0;
+
+    return newCodeBlock->extractExceptionInfo();
+}
+
+ExceptionInfo* EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
+{
+    RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source);
+
+    ScopeChain scopeChain(scopeChainNode);
+    JSGlobalObject* globalObject = scopeChain.globalObject();
+
+    OwnPtr<EvalCodeBlock> newCodeBlock(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
+
+    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(newEvalBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get()));
+    generator->setRegeneratingForExceptionInfo(static_cast<EvalCodeBlock*>(codeBlock));
+    generator->generate();
+
+    ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
+
+#if ENABLE(JIT)
+    JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
+    ASSERT(newJITCode.size() == generatedJITCode().size());
+#endif
+
+    return newCodeBlock->extractExceptionInfo();
+}
+
+void FunctionExecutable::recompile(ExecState*)
+{
+    delete m_codeBlock;
+    m_codeBlock = 0;
+    m_numParameters = NUM_PARAMETERS_NOT_COMPILED;
+#if ENABLE(JIT)
+    m_jitCode = JITCode();
+#endif
+}
+
+PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
+{
+    RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), debugger, exec, source, errLine, errMsg);
+    if (!program)
+        return 0;
+
+    StatementNode* exprStatement = program->singleStatement();
+    ASSERT(exprStatement);
+    ASSERT(exprStatement->isExprStatement());
+    if (!exprStatement || !exprStatement->isExprStatement())
+        return 0;
+
+    ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
+    ASSERT(funcExpr);
+    ASSERT(funcExpr->isFuncExprNode());
+    if (!funcExpr || !funcExpr->isFuncExprNode())
+        return 0;
+
+    FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
+    ASSERT(body);
+    return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
+}
+
+UString FunctionExecutable::paramString() const
+{
+    FunctionParameters& parameters = *m_parameters;
+    StringBuilder builder;
+    for (size_t pos = 0; pos < parameters.size(); ++pos) {
+        if (!builder.isEmpty())
+            builder.append(", ");
+        builder.append(parameters[pos].ustring());
+    }
+    return builder.release();
+}
+
+};
+
+
diff --git a/runtime/Executable.h b/runtime/Executable.h
new file mode 100644 (file)
index 0000000..f74abe9
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef Executable_h
+#define Executable_h
+
+#include "JSFunction.h"
+#include "Interpreter.h"
+#include "Nodes.h"
+#include "SamplingTool.h"
+
+namespace JSC {
+
+    class CodeBlock;
+    class Debugger;
+    class EvalCodeBlock;
+    class ProgramCodeBlock;
+    class ScopeChainNode;
+
+    struct ExceptionInfo;
+
+    class ExecutableBase : public RefCounted<ExecutableBase> {
+        friend class JIT;
+
+    protected:
+        static const int NUM_PARAMETERS_IS_HOST = 0;
+        static const int NUM_PARAMETERS_NOT_COMPILED = -1;
+    
+    public:
+        ExecutableBase(int numParameters)
+            : m_numParameters(numParameters)
+        {
+        }
+
+        virtual ~ExecutableBase() {}
+
+        bool isHostFunction() const { return m_numParameters == NUM_PARAMETERS_IS_HOST; }
+
+    protected:
+        int m_numParameters;
+
+#if ENABLE(JIT)
+    public:
+        JITCode& generatedJITCode()
+        {
+            ASSERT(m_jitCode);
+            return m_jitCode;
+        }
+
+        ExecutablePool* getExecutablePool()
+        {
+            return m_jitCode.getExecutablePool();
+        }
+
+    protected:
+        JITCode m_jitCode;
+#endif
+    };
+
+#if ENABLE(JIT)
+    class NativeExecutable : public ExecutableBase {
+    public:
+        NativeExecutable(ExecState* exec)
+            : ExecutableBase(NUM_PARAMETERS_IS_HOST)
+        {
+            m_jitCode = JITCode(JITCode::HostFunction(exec->globalData().jitStubs.ctiNativeCallThunk()));
+        }
+
+        ~NativeExecutable();
+    };
+#endif
+
+    class VPtrHackExecutable : public ExecutableBase {
+    public:
+        VPtrHackExecutable()
+            : ExecutableBase(NUM_PARAMETERS_IS_HOST)
+        {
+        }
+
+        ~VPtrHackExecutable();
+    };
+
+    class ScriptExecutable : public ExecutableBase {
+    public:
+        ScriptExecutable(JSGlobalData* globalData, const SourceCode& source)
+            : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+            , m_source(source)
+            , m_features(0)
+        {
+#if ENABLE(CODEBLOCK_SAMPLING)
+            if (SamplingTool* sampler = globalData->interpreter->sampler())
+                sampler->notifyOfScope(this);
+#else
+            UNUSED_PARAM(globalData);
+#endif
+        }
+
+        ScriptExecutable(ExecState* exec, const SourceCode& source)
+            : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+            , m_source(source)
+            , m_features(0)
+        {
+#if ENABLE(CODEBLOCK_SAMPLING)
+            if (SamplingTool* sampler = exec->globalData().interpreter->sampler())
+                sampler->notifyOfScope(this);
+#else
+            UNUSED_PARAM(exec);
+#endif
+        }
+
+        const SourceCode& source() { return m_source; }
+        intptr_t sourceID() const { return m_source.provider()->asID(); }
+        const UString& sourceURL() const { return m_source.provider()->url(); }
+        int lineNo() const { return m_firstLine; }
+        int lastLine() const { return m_lastLine; }
+
+        bool usesEval() const { return m_features & EvalFeature; }
+        bool usesArguments() const { return m_features & ArgumentsFeature; }
+        bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
+
+        virtual ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0;
+
+    protected:
+        void recordParse(CodeFeatures features, int firstLine, int lastLine)
+        {
+            m_features = features;
+            m_firstLine = firstLine;
+            m_lastLine = lastLine;
+        }
+
+        SourceCode m_source;
+        CodeFeatures m_features;
+        int m_firstLine;
+        int m_lastLine;
+    };
+
+    class EvalExecutable : public ScriptExecutable {
+    public:
+
+        ~EvalExecutable();
+
+        EvalCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
+        {
+            if (!m_evalCodeBlock) {
+                JSObject* error = compile(exec, scopeChainNode);
+                ASSERT_UNUSED(!error, error);
+            }
+            return *m_evalCodeBlock;
+        }
+
+        JSObject* compile(ExecState*, ScopeChainNode*);
+
+        ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
+        static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); }
+
+    private:
+        EvalExecutable(ExecState* exec, const SourceCode& source)
+            : ScriptExecutable(exec, source)
+            , m_evalCodeBlock(0)
+        {
+        }
+        EvalCodeBlock* m_evalCodeBlock;
+
+#if ENABLE(JIT)
+    public:
+        JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+        {
+            if (!m_jitCode)
+                generateJITCode(exec, scopeChainNode);
+            return m_jitCode;
+        }
+
+    private:
+        void generateJITCode(ExecState*, ScopeChainNode*);
+#endif
+    };
+
+    class ProgramExecutable : public ScriptExecutable {
+    public:
+        static PassRefPtr<ProgramExecutable> create(ExecState* exec, const SourceCode& source)
+        {
+            return adoptRef(new ProgramExecutable(exec, source));
+        }
+
+        ~ProgramExecutable();
+
+        ProgramCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
+        {
+            if (!m_programCodeBlock) {
+                JSObject* error = compile(exec, scopeChainNode);
+                ASSERT_UNUSED(!error, error);
+            }
+            return *m_programCodeBlock;
+        }
+
+        JSObject* checkSyntax(ExecState*);
+        JSObject* compile(ExecState*, ScopeChainNode*);
+
+        // CodeBlocks for program code are transient and therefore do not gain from from throwing out there exception information.
+        ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) { ASSERT_NOT_REACHED(); return 0; }
+
+    private:
+        ProgramExecutable(ExecState* exec, const SourceCode& source)
+            : ScriptExecutable(exec, source)
+            , m_programCodeBlock(0)
+        {
+        }
+        ProgramCodeBlock* m_programCodeBlock;
+
+#if ENABLE(JIT)
+    public:
+        JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+        {
+            if (!m_jitCode)
+                generateJITCode(exec, scopeChainNode);
+            return m_jitCode;
+        }
+
+    private:
+        void generateJITCode(ExecState*, ScopeChainNode*);
+#endif
+    };
+
+    class FunctionExecutable : public ScriptExecutable {
+        friend class JIT;
+    public:
+        static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+        {
+            return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, firstLine, lastLine));
+        }
+
+        static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+        {
+            return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, firstLine, lastLine));
+        }
+
+        ~FunctionExecutable();
+
+        JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
+        {
+            return new (exec) JSFunction(exec, this, scopeChain);
+        }
+
+        CodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode) 
+        {
+            ASSERT(scopeChainNode);
+            if (!m_codeBlock)
+                compile(exec, scopeChainNode);
+            return *m_codeBlock;
+        }
+
+        bool isGenerated() const
+        {
+            return m_codeBlock;
+        }
+
+        CodeBlock& generatedBytecode()
+        {
+            ASSERT(m_codeBlock);
+            return *m_codeBlock;
+        }
+
+        const Identifier& name() { return m_name; }
+        size_t parameterCount() const { return m_parameters->size(); }
+        size_t variableCount() const { return m_numVariables; }
+        UString paramString() const;
+
+        void recompile(ExecState*);
+        ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
+        void markAggregate(MarkStack& markStack);
+        static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
+
+    private:
+        FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+            : ScriptExecutable(globalData, source)
+            , m_forceUsesArguments(forceUsesArguments)
+            , m_parameters(parameters)
+            , m_codeBlock(0)
+            , m_name(name)
+            , m_numVariables(0)
+        {
+            m_firstLine = firstLine;
+            m_lastLine = lastLine;
+        }
+
+        FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+            : ScriptExecutable(exec, source)
+            , m_forceUsesArguments(forceUsesArguments)
+            , m_parameters(parameters)
+            , m_codeBlock(0)
+            , m_name(name)
+            , m_numVariables(0)
+        {
+            m_firstLine = firstLine;
+            m_lastLine = lastLine;
+        }
+
+        void compile(ExecState*, ScopeChainNode*);
+
+        bool m_forceUsesArguments;
+        RefPtr<FunctionParameters> m_parameters;
+        CodeBlock* m_codeBlock;
+        Identifier m_name;
+        size_t m_numVariables;
+
+#if ENABLE(JIT)
+    public:
+        JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+        {
+            if (!m_jitCode)
+                generateJITCode(exec, scopeChainNode);
+            return m_jitCode;
+        }
+
+    private:
+        void generateJITCode(ExecState*, ScopeChainNode*);
+#endif
+    };
+
+    inline FunctionExecutable* JSFunction::jsExecutable() const
+    {
+        ASSERT(!isHostFunctionNonInline());
+        return static_cast<FunctionExecutable*>(m_executable.get());
+    }
+
+    inline bool JSFunction::isHostFunction() const
+    {
+        ASSERT(m_executable);
+        return m_executable->isHostFunction();
+    }
+
+}
+
+#endif
index f4f5cc8e611570048bf68dc4eeffcfbb01885e6a..9d55dd109b00ffd40d9aa9ff0999faf6654b7c98 100644 (file)
 #include "config.h"
 #include "FunctionConstructor.h"
 
 #include "config.h"
 #include "FunctionConstructor.h"
 
+#include "Debugger.h"
 #include "FunctionPrototype.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include "FunctionPrototype.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
-#include "Parser.h"
-#include "Debugger.h"
 #include "Lexer.h"
 #include "Nodes.h"
 #include "Lexer.h"
 #include "Nodes.h"
+#include "Parser.h"
+#include "StringBuilder.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
 
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
 
-FunctionConstructor::FunctionConstructor(ExecState* exec, PassRefPtr<Structure> structure, FunctionPrototype* functionPrototype)
+FunctionConstructor::FunctionConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, FunctionPrototype* functionPrototype)
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, functionPrototype->classInfo()->className))
 {
     putDirectWithoutTransition(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, functionPrototype->classInfo()->className))
 {
     putDirectWithoutTransition(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
@@ -66,32 +67,6 @@ CallType FunctionConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
     return CallTypeHost;
 }
 
-FunctionBodyNode* extractFunctionBody(ProgramNode* program)
-{
-    if (!program)
-        return 0;
-
-    StatementVector& children = program->children();
-    if (children.size() != 1)
-        return 0;
-
-    StatementNode* exprStatement = children[0];
-    ASSERT(exprStatement);
-    ASSERT(exprStatement->isExprStatement());
-    if (!exprStatement || !exprStatement->isExprStatement())
-        return 0;
-
-    ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
-    ASSERT(funcExpr);
-    ASSERT(funcExpr->isFuncExprNode());
-    if (!funcExpr || !funcExpr->isFuncExprNode())
-        return 0;
-
-    FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
-    ASSERT(body);
-    return body;
-}
-
 // ECMA 15.3.2 The Function Constructor
 JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
 {
 // ECMA 15.3.2 The Function Constructor
 JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
 {
@@ -102,26 +77,31 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi
     if (args.isEmpty())
         program = "(function() { \n})";
     else if (args.size() == 1)
     if (args.isEmpty())
         program = "(function() { \n})";
     else if (args.size() == 1)
-        program = "(function() { " + args.at(0).toString(exec) + "\n})";
+        program = makeString("(function() { ", args.at(0).toString(exec), "\n})");
     else {
     else {
-        program = "(function(" + args.at(0).toString(exec);
-        for (size_t i = 1; i < args.size() - 1; i++)
-            program += "," + args.at(i).toString(exec);
-        program += ") { " + args.at(args.size() - 1).toString(exec) + "\n})";
+        StringBuilder builder;
+        builder.append("(function(");
+        builder.append(args.at(0).toString(exec));
+        for (size_t i = 1; i < args.size() - 1; i++) {
+            builder.append(",");
+            builder.append(args.at(i).toString(exec));
+        }
+        builder.append(") { ");
+        builder.append(args.at(args.size() - 1).toString(exec));
+        builder.append("\n})");
+        program = builder.release();
     }
 
     int errLine;
     UString errMsg;
     SourceCode source = makeSource(program, sourceURL, lineNumber);
     }
 
     int errLine;
     UString errMsg;
     SourceCode source = makeSource(program, sourceURL, lineNumber);
-    RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-
-    FunctionBodyNode* body = extractFunctionBody(programNode.get());
-    if (!body)
+    RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+    if (!function)
         return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
         return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
-    ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue());
-    return new (exec) JSFunction(exec, functionName, body, scopeChain.node());
+    ScopeChain scopeChain(globalObject, globalObject->globalData(), globalObject, exec->globalThisValue());
+    return new (exec) JSFunction(exec, function, scopeChain.node());
 }
 
 // ECMA 15.3.2 The Function Constructor
 }
 
 // ECMA 15.3.2 The Function Constructor
index 124b35484a569e95b88ad4015e4587785ce4ae1f..197f320c2896627872741ebf57ca1e94b0043263 100644 (file)
 namespace JSC {
 
     class FunctionPrototype;
 namespace JSC {
 
     class FunctionPrototype;
-    class ProgramNode;
-    class FunctionBodyNode;
 
     class FunctionConstructor : public InternalFunction {
     public:
 
     class FunctionConstructor : public InternalFunction {
     public:
-        FunctionConstructor(ExecState*, PassRefPtr<Structure>, FunctionPrototype*);
+        FunctionConstructor(ExecState*, NonNullPassRefPtr<Structure>, FunctionPrototype*);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
@@ -41,8 +39,6 @@ namespace JSC {
     JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
     JSObject* constructFunction(ExecState*, const ArgList&);
 
     JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
     JSObject* constructFunction(ExecState*, const ArgList&);
 
-    FunctionBodyNode* extractFunctionBody(ProgramNode*);
-
 } // namespace JSC
 
 #endif // FunctionConstructor_h
 } // namespace JSC
 
 #endif // FunctionConstructor_h
index 9ba2144190571d9d789b796eeff47db1bd1be287..f08bd5e1f9d883c8dd814fe004ef8d57abca5e10 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -37,7 +37,7 @@ static JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*, JSObject*, JS
 static JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*, JSObject*, JSValue, const ArgList&);
 static JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*, JSObject*, JSValue, const ArgList&);
 
 static JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*, JSObject*, JSValue, const ArgList&);
 static JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*, JSObject*, JSValue, const ArgList&);
 
-FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<Structure> structure)
+FunctionPrototype::FunctionPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
     : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier)
 {
     putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
     : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier)
 {
     putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
@@ -76,7 +76,7 @@ static inline void insertSemicolonIfNeeded(UString& functionBody)
         UChar ch = functionBody[i];
         if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) {
             if (ch != ';' && ch != '}')
         UChar ch = functionBody[i];
         if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) {
             if (ch != ';' && ch != '}')
-                functionBody = functionBody.substr(0, i + 1) + ";" + functionBody.substr(i + 1, functionBody.size() - (i + 1));
+                functionBody = makeString(functionBody.substr(0, i + 1), ";", functionBody.substr(i + 1, functionBody.size() - (i + 1)));
             return;
         }
     }
             return;
         }
     }
@@ -84,18 +84,19 @@ static inline void insertSemicolonIfNeeded(UString& functionBody)
 
 JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 
 JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (thisValue.isObject(&JSFunction::info)) {
+    if (thisValue.inherits(&JSFunction::info)) {
         JSFunction* function = asFunction(thisValue);
         if (!function->isHostFunction()) {
         JSFunction* function = asFunction(thisValue);
         if (!function->isHostFunction()) {
-            UString functionBody = function->body()->toSourceString();
-            insertSemicolonIfNeeded(functionBody);
-            return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->body()->paramString() + ") " + functionBody);
+            FunctionExecutable* executable = function->jsExecutable();
+            UString sourceString = executable->source().toString();
+            insertSemicolonIfNeeded(sourceString);
+            return jsString(exec, makeString("function ", function->name(exec), "(", executable->paramString(), ") ", sourceString));
         }
     }
 
         }
     }
 
-    if (thisValue.isObject(&InternalFunction::info)) {
+    if (thisValue.inherits(&InternalFunction::info)) {
         InternalFunction* function = asInternalFunction(thisValue);
         InternalFunction* function = asInternalFunction(thisValue);
-        return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n    [native code]\n}");
+        return jsString(exec, makeString("function ", function->name(exec), "() {\n    [native code]\n}"));
     }
 
     return throwError(exec, TypeError);
     }
 
     return throwError(exec, TypeError);
index 607ddab15a9902f93e77788b61f5d1e249d9f8e1..af783f7b2b3be2678d79ed25bf273714c0488cbd 100644 (file)
@@ -29,12 +29,12 @@ namespace JSC {
 
     class FunctionPrototype : public InternalFunction {
     public:
 
     class FunctionPrototype : public InternalFunction {
     public:
-        FunctionPrototype(ExecState*, PassRefPtr<Structure>);
+        FunctionPrototype(ExecState*, NonNullPassRefPtr<Structure>);
         void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction);
 
         static PassRefPtr<Structure> createStructure(JSValue proto)
         {
         void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction);
 
         static PassRefPtr<Structure> createStructure(JSValue proto)
         {
-            return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
+            return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
 
     private:
         }
 
     private:
index cd1b40a15f28a8a94a548209a5a82cf044d5d766..7e54053f96cce73b5560a82e5e810e1e5d280f6c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2004, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 
 namespace JSC {
 
 
 namespace JSC {
 
-void GetterSetter::mark()
+void GetterSetter::markChildren(MarkStack& markStack)
 {
 {
-    JSCell::mark();
+    JSCell::markChildren(markStack);
 
 
-    if (m_getter && !m_getter->marked())
-        m_getter->mark();
-    if (m_setter && !m_setter->marked())
-        m_setter->mark();
-}
-
-JSValue GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
-{
-    ASSERT_NOT_REACHED();
-    return jsNull();
-}
-
-bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValue& value)
-{
-    ASSERT_NOT_REACHED();
-    number = 0;
-    value = JSValue();
-    return true;
-}
-
-bool GetterSetter::toBoolean(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return false;
-}
-
-double GetterSetter::toNumber(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return 0.0;
-}
-
-UString GetterSetter::toString(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return UString::null();
-}
-
-JSObject* GetterSetter::toObject(ExecState* exec) const
-{
-    ASSERT_NOT_REACHED();
-    return jsNull().toObject(exec);
+    if (m_getter)
+        markStack.append(m_getter);
+    if (m_setter)
+        markStack.append(m_setter);
 }
 
 bool GetterSetter::isGetterSetter() const
 }
 
 bool GetterSetter::isGetterSetter() const
index e6b74a1ed0cfb354be6f9fe159ca114b332d4e87..4e47361ec8eb9d63103dcf25bd00ebd944e7d631 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -25,6 +25,8 @@
 
 #include "JSCell.h"
 
 
 #include "JSCell.h"
 
+#include "CallFrame.h"
+
 namespace JSC {
 
     class JSObject;
 namespace JSC {
 
     class JSObject;
@@ -33,30 +35,26 @@ namespace JSC {
     // for a property.
     class GetterSetter : public JSCell {
     public:
     // for a property.
     class GetterSetter : public JSCell {
     public:
-        GetterSetter()
-            : JSCell(0)
+        GetterSetter(ExecState* exec)
+            : JSCell(exec->globalData().getterSetterStructure.get())
             , m_getter(0)
             , m_setter(0)
         {
         }
 
             , m_getter(0)
             , m_setter(0)
         {
         }
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         JSObject* getter() const { return m_getter; }
         void setGetter(JSObject* getter) { m_getter = getter; }
         JSObject* setter() const { return m_setter; }
         void setSetter(JSObject* setter) { m_setter = setter; }
 
         JSObject* getter() const { return m_getter; }
         void setGetter(JSObject* getter) { m_getter = getter; }
         JSObject* setter() const { return m_setter; }
         void setSetter(JSObject* setter) { m_setter = setter; }
-
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount);
+        }
     private:
         virtual bool isGetterSetter() const;
 
     private:
         virtual bool isGetterSetter() const;
 
-        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
-        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
-        virtual bool toBoolean(ExecState*) const;
-        virtual double toNumber(ExecState*) const;
-        virtual UString toString(ExecState*) const;
-        virtual JSObject* toObject(ExecState*) const;
-
         JSObject* m_getter;
         JSObject* m_setter;  
     };
         JSObject* m_getter;
         JSObject* m_setter;  
     };
index b0d4c2523e8c945ae8fbda231cc9f9eafa3cbd94..c26002ba171dcd69cc217d573086475f2a3591a2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -32,18 +32,17 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(GlobalEvalFunction);
 
 
 ASSERT_CLASS_FITS_IN_CELL(GlobalEvalFunction);
 
-GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, PassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)
+GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)
     : PrototypeFunction(exec, structure, len, name, function)
     , m_cachedGlobalObject(cachedGlobalObject)
 {
     ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);
 }
 
     : PrototypeFunction(exec, structure, len, name, function)
     , m_cachedGlobalObject(cachedGlobalObject)
 {
     ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);
 }
 
-void GlobalEvalFunction::mark()
+void GlobalEvalFunction::markChildren(MarkStack& markStack)
 {
 {
-    PrototypeFunction::mark();
-    if (!m_cachedGlobalObject->marked())
-        m_cachedGlobalObject->mark();
+    PrototypeFunction::markChildren(markStack);
+    markStack.append(m_cachedGlobalObject);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 49b1847152dc8ade636aba4f093f28fcf927ecb4..a14ce4d0442ca7e1a3a515cc2b573c3e8474773a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -32,11 +32,19 @@ namespace JSC {
 
     class GlobalEvalFunction : public PrototypeFunction {
     public:
 
     class GlobalEvalFunction : public PrototypeFunction {
     public:
-        GlobalEvalFunction(ExecState*, PassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject);
+        GlobalEvalFunction(ExecState*, NonNullPassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject);
         JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; }
 
         JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; }
 
+        static PassRefPtr<Structure> createStructure(JSValue prototype) 
+        { 
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+        }
+
+    protected:
+        static const unsigned StructureFlags = ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | PrototypeFunction::StructureFlags;
+
     private:
     private:
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         JSGlobalObject* m_cachedGlobalObject;
     };
 
         JSGlobalObject* m_cachedGlobalObject;
     };
index 040c123e55897f2216fe7cba20c20a5461fef58c..76e762c97e5750f979e1d42d4f8529c5a699be68 100644 (file)
 #include <wtf/FastMalloc.h>
 #include <wtf/HashSet.h>
 
 #include <wtf/FastMalloc.h>
 #include <wtf/HashSet.h>
 
+using WTF::ThreadSpecific;
+
 namespace JSC {
 
 typedef HashMap<const char*, RefPtr<UString::Rep>, PtrHash<const char*> > LiteralIdentifierTable;
 
 namespace JSC {
 
 typedef HashMap<const char*, RefPtr<UString::Rep>, PtrHash<const char*> > LiteralIdentifierTable;
 
-class IdentifierTable {
+class IdentifierTable : public FastAllocBase {
 public:
     ~IdentifierTable()
     {
         HashSet<UString::Rep*>::iterator end = m_table.end();
         for (HashSet<UString::Rep*>::iterator iter = m_table.begin(); iter != end; ++iter)
 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);
+            (*iter)->setIsIdentifier(false);
     }
     
     std::pair<HashSet<UString::Rep*>::iterator, bool> add(UString::Rep* value)
     {
         std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add(value);
     }
     
     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);
+        (*result.first)->setIsIdentifier(true);
         return result;
     }
 
         return result;
     }
 
@@ -52,7 +54,7 @@ public:
     std::pair<HashSet<UString::Rep*>::iterator, bool> add(U value)
     {
         std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add<U, V>(value);
     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);
+        (*result.first)->setIsIdentifier(true);
         return result;
     }
 
         return result;
     }
 
@@ -77,7 +79,7 @@ void deleteIdentifierTable(IdentifierTable* table)
 
 bool Identifier::equal(const UString::Rep* r, const char* s)
 {
 
 bool Identifier::equal(const UString::Rep* r, const char* s)
 {
-    int length = r->len;
+    int length = r->size();
     const UChar* d = r->data();
     for (int i = 0; i != length; ++i)
         if (d[i] != (unsigned char)s[i])
     const UChar* d = r->data();
     for (int i = 0; i != length; ++i)
         if (d[i] != (unsigned char)s[i])
@@ -87,7 +89,7 @@ bool Identifier::equal(const UString::Rep* r, const char* s)
 
 bool Identifier::equal(const UString::Rep* r, const UChar* s, int length)
 {
 
 bool Identifier::equal(const UString::Rep* r, const UChar* s, int length)
 {
-    if (r->len != length)
+    if (r->size() != length)
         return false;
     const UChar* d = r->data();
     for (int i = 0; i != length; ++i)
         return false;
     const UChar* d = r->data();
     for (int i = 0; i != length; ++i)
@@ -110,13 +112,11 @@ struct CStringTranslator {
     static void translate(UString::Rep*& location, const char* c, unsigned hash)
     {
         size_t length = strlen(c);
     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));
+        UChar* d;
+        UString::Rep* r = UString::Rep::createUninitialized(length, d).releaseRef();
         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
         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->_hash = hash;
-
+        r->setHash(hash);
         location = r;
     }
 };
         location = r;
     }
 };
@@ -175,13 +175,11 @@ struct UCharBufferTranslator {
 
     static void translate(UString::Rep*& location, const UCharBuffer& buf, unsigned hash)
     {
 
     static void translate(UString::Rep*& location, const UCharBuffer& buf, unsigned hash)
     {
-        UChar* d = static_cast<UChar*>(fastMalloc(sizeof(UChar) * buf.length));
+        UChar* d;
+        UString::Rep* r = UString::Rep::createUninitialized(buf.length, d).releaseRef();
         for (unsigned i = 0; i != buf.length; i++)
             d[i] = buf.s[i];
         for (unsigned i = 0; i != buf.length; i++)
             d[i] = buf.s[i];
-        
-        UString::Rep* r = UString::Rep::create(d, buf.length).releaseRef();
-        r->_hash = hash;
-        
+        r->setHash(hash);
         location = r; 
     }
 };
         location = r; 
     }
 };
@@ -212,19 +210,19 @@ PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const UChar* s, int le
 
 PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UString::Rep* r)
 {
 
 PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UString::Rep* r)
 {
-    ASSERT(!r->identifierTable());
-    if (r->len == 1) {
+    ASSERT(!r->isIdentifier());
+    if (r->size() == 1) {
         UChar c = r->data()[0];
         if (c <= 0xFF)
             r = globalData->smallStrings.singleCharacterStringRep(c);
         UChar c = r->data()[0];
         if (c <= 0xFF)
             r = globalData->smallStrings.singleCharacterStringRep(c);
-            if (r->identifierTable()) {
+            if (r->isIdentifier()) {
 #ifndef NDEBUG
                 checkSameIdentifierTable(globalData, r);
 #endif
                 return r;
             }
     }
 #ifndef NDEBUG
                 checkSameIdentifierTable(globalData, r);
 #endif
                 return r;
             }
     }
-    if (!r->len) {
+    if (!r->size()) {
         UString::Rep::empty().hash();
         return &UString::Rep::empty();
     }
         UString::Rep::empty().hash();
         return &UString::Rep::empty();
     }
@@ -238,19 +236,19 @@ PassRefPtr<UString::Rep> Identifier::addSlowCase(ExecState* exec, UString::Rep*
 
 void Identifier::remove(UString::Rep* r)
 {
 
 void Identifier::remove(UString::Rep* r)
 {
-    r->identifierTable()->remove(r);
+    currentIdentifierTable()->remove(r);
 }
 
 #ifndef NDEBUG
 
 }
 
 #ifndef NDEBUG
 
-void Identifier::checkSameIdentifierTable(ExecState* exec, UString::Rep* rep)
+void Identifier::checkSameIdentifierTable(ExecState* exec, UString::Rep*)
 {
 {
-    ASSERT(rep->identifierTable() == exec->globalData().identifierTable);
+    ASSERT_UNUSED(exec, exec->globalData().identifierTable == currentIdentifierTable());
 }
 
 }
 
-void Identifier::checkSameIdentifierTable(JSGlobalData* globalData, UString::Rep* rep)
+void Identifier::checkSameIdentifierTable(JSGlobalData* globalData, UString::Rep*)
 {
 {
-    ASSERT(rep->identifierTable() == globalData->identifierTable);
+    ASSERT_UNUSED(globalData, globalData->identifierTable == currentIdentifierTable());
 }
 
 #else
 }
 
 #else
@@ -265,4 +263,36 @@ void Identifier::checkSameIdentifierTable(JSGlobalData*, UString::Rep*)
 
 #endif
 
 
 #endif
 
+ThreadSpecific<ThreadIdentifierTableData>* g_identifierTableSpecific = 0;
+ThreadIdentifierTableData* g_identifierTableMain = 0;
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+pthread_once_t createIdentifierTableSpecificOnce = PTHREAD_ONCE_INIT;
+static void createIdentifierTableSpecificCallback()
+{
+    ASSERT(!g_identifierTableSpecific);
+    g_identifierTableSpecific = new ThreadSpecific<ThreadIdentifierTableData>();
+    ASSERT(!g_identifierTableMain);
+    g_identifierTableMain = new ThreadIdentifierTableData();
+}
+void createIdentifierTableSpecific()
+{
+    pthread_once(&createIdentifierTableSpecificOnce, createIdentifierTableSpecificCallback);
+    ASSERT(g_identifierTableSpecific);
+    ASSERT(g_identifierTableMain);
+}
+
+#else 
+
+void createIdentifierTableSpecific()
+{
+    ASSERT(!g_identifierTableSpecific);
+    g_identifierTableSpecific = new ThreadSpecific<ThreadIdentifierTableData>();
+    ASSERT(!g_identifierTableMain);
+    g_identifierTableMain = new ThreadIdentifierTableData();
+}
+
+#endif
+
 } // namespace JSC
 } // namespace JSC
index 631cf42f7edfb4f3ffeca857fe88cbe94e14e615..35822258ef37a2d4fd9c565d4450d73b16fd85f3 100644 (file)
@@ -22,6 +22,7 @@
 #define Identifier_h
 
 #include "JSGlobalData.h"
 #define Identifier_h
 
 #include "JSGlobalData.h"
+#include "ThreadSpecific.h"
 #include "UString.h"
 
 namespace JSC {
 #include "UString.h"
 
 namespace JSC {
@@ -54,6 +55,8 @@ namespace JSC {
         const char* ascii() const { return _ustring.ascii(); }
         
         static Identifier from(ExecState* exec, unsigned y) { return Identifier(exec, UString::from(y)); }
         const char* ascii() const { return _ustring.ascii(); }
         
         static Identifier from(ExecState* exec, unsigned y) { return Identifier(exec, UString::from(y)); }
+        static Identifier from(ExecState* exec, int y) { return Identifier(exec, UString::from(y)); }
+        static Identifier from(ExecState* exec, double y) { return Identifier(exec, UString::from(y)); }
         
         bool isNull() const { return _ustring.isNull(); }
         bool isEmpty() const { return _ustring.isEmpty(); }
         
         bool isNull() const { return _ustring.isNull(); }
         bool isEmpty() const { return _ustring.isEmpty(); }
@@ -90,7 +93,7 @@ namespace JSC {
 
         static PassRefPtr<UString::Rep> add(ExecState* exec, UString::Rep* r)
         {
 
         static PassRefPtr<UString::Rep> add(ExecState* exec, UString::Rep* r)
         {
-            if (r->identifierTable()) {
+            if (r->isIdentifier()) {
 #ifndef NDEBUG
                 checkSameIdentifierTable(exec, r);
 #endif
 #ifndef NDEBUG
                 checkSameIdentifierTable(exec, r);
 #endif
@@ -100,7 +103,7 @@ namespace JSC {
         }
         static PassRefPtr<UString::Rep> add(JSGlobalData* globalData, UString::Rep* r)
         {
         }
         static PassRefPtr<UString::Rep> add(JSGlobalData* globalData, UString::Rep* r)
         {
-            if (r->identifierTable()) {
+            if (r->isIdentifier()) {
 #ifndef NDEBUG
                 checkSameIdentifierTable(globalData, r);
 #endif
 #ifndef NDEBUG
                 checkSameIdentifierTable(globalData, r);
 #endif
@@ -139,6 +142,97 @@ namespace JSC {
     IdentifierTable* createIdentifierTable();
     void deleteIdentifierTable(IdentifierTable*);
 
     IdentifierTable* createIdentifierTable();
     void deleteIdentifierTable(IdentifierTable*);
 
+    struct ThreadIdentifierTableData {
+        ThreadIdentifierTableData()
+            : defaultIdentifierTable(0)
+            , currentIdentifierTable(0)
+        {
+        }
+
+        IdentifierTable* defaultIdentifierTable;
+        IdentifierTable* currentIdentifierTable;
+    };
+
+    extern WTF::ThreadSpecific<ThreadIdentifierTableData>* g_identifierTableSpecific;
+    extern ThreadIdentifierTableData* g_identifierTableMain;
+    void createIdentifierTableSpecific();
+
+    inline IdentifierTable* defaultIdentifierTable()
+    {
+        if (isMainThread() || pthread_main_np()) {
+            if (!g_identifierTableMain)
+                createIdentifierTableSpecific();
+            return g_identifierTableMain->defaultIdentifierTable;
+        }
+        if (!g_identifierTableSpecific)
+            createIdentifierTableSpecific();
+        ThreadIdentifierTableData& data = **g_identifierTableSpecific;
+
+        return data.defaultIdentifierTable;
+    }
+
+    inline void setDefaultIdentifierTable(IdentifierTable* identifierTable)
+    {
+        if (isMainThread() || pthread_main_np()) {
+            if (!g_identifierTableMain)
+                createIdentifierTableSpecific();
+            g_identifierTableMain->defaultIdentifierTable = identifierTable;
+            return;
+        }
+        if (!g_identifierTableSpecific)
+            createIdentifierTableSpecific();
+        ThreadIdentifierTableData& data = **g_identifierTableSpecific;
+
+        data.defaultIdentifierTable = identifierTable;
+    }
+
+    inline IdentifierTable* currentIdentifierTable()
+    {
+        if (isMainThread() || pthread_main_np()) {
+            if (!g_identifierTableMain)
+                createIdentifierTableSpecific();
+            return g_identifierTableMain->currentIdentifierTable;
+        }
+        if (!g_identifierTableSpecific)
+            createIdentifierTableSpecific();
+        ThreadIdentifierTableData& data = **g_identifierTableSpecific;
+
+        return data.currentIdentifierTable;
+    }
+
+    inline IdentifierTable* setCurrentIdentifierTable(IdentifierTable* identifierTable)
+    {
+        if (isMainThread() || pthread_main_np()) {
+            if (!g_identifierTableMain)
+                createIdentifierTableSpecific();
+            IdentifierTable* oldIdentifierTable = g_identifierTableMain->currentIdentifierTable;
+            g_identifierTableMain->currentIdentifierTable = identifierTable;
+            return oldIdentifierTable;
+        }
+        if (!g_identifierTableSpecific)
+            createIdentifierTableSpecific();
+        ThreadIdentifierTableData& data = **g_identifierTableSpecific;
+
+        IdentifierTable* oldIdentifierTable = data.currentIdentifierTable;
+        data.currentIdentifierTable = identifierTable;
+        return oldIdentifierTable;
+    }
+
+    inline void resetCurrentIdentifierTable()
+    {
+        if (isMainThread() || pthread_main_np()) {
+            if (!g_identifierTableMain)
+                createIdentifierTableSpecific();
+            g_identifierTableMain->currentIdentifierTable = g_identifierTableMain->defaultIdentifierTable;
+            return;
+        }
+        if (!g_identifierTableSpecific)
+            createIdentifierTableSpecific();
+        ThreadIdentifierTableData& data = **g_identifierTableSpecific;
+
+        data.currentIdentifierTable = data.defaultIdentifierTable;
+    }
+
 } // namespace JSC
 
 #endif // Identifier_h
 } // namespace JSC
 
 #endif // Identifier_h
index fea89f875e5c8afe4ade5e56c0ed1dbe4893f2a6..2605a9a7cde0e52532a1ea1e16f1657b6da8fc81 100644 (file)
@@ -41,7 +41,7 @@ using namespace WTF;
 
 namespace JSC {
 
 
 namespace JSC {
 
-#if PLATFORM(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS)
+#if OS(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS)
 static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT;
 #endif
 
 static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT;
 #endif
 
@@ -49,15 +49,16 @@ static void initializeThreadingOnce()
 {
     WTF::initializeThreading();
     initializeUString();
 {
     WTF::initializeThreading();
     initializeUString();
+    JSGlobalData::storeVPtrs();
 #if ENABLE(JSC_MULTIPLE_THREADS)
     s_dtoaP5Mutex = new Mutex;
 #if ENABLE(JSC_MULTIPLE_THREADS)
     s_dtoaP5Mutex = new Mutex;
-    WTF::initializeDates();
+    initializeDates();
 #endif
 }
 
 void initializeThreading()
 {
 #endif
 }
 
 void initializeThreading()
 {
-#if PLATFORM(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS)
+#if OS(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS)
     pthread_once(&initializeThreadingKeyOnce, initializeThreadingOnce);
 #else
     static bool initializedThreading = false;
     pthread_once(&initializeThreadingKeyOnce, initializeThreadingOnce);
 #else
     static bool initializedThreading = false;
index b5c95715592edd5a298439d5a91b5beccd617541..c48d6288e5c8406d8b377d4cdebe70af386b729f 100644 (file)
@@ -37,35 +37,35 @@ const ClassInfo* InternalFunction::classInfo() const
     return &info;
 }
 
     return &info;
 }
 
-InternalFunction::InternalFunction(JSGlobalData* globalData, PassRefPtr<Structure> structure, const Identifier& name)
+InternalFunction::InternalFunction(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const Identifier& name)
     : JSObject(structure)
 {
     putDirect(globalData->propertyNames->name, jsString(globalData, name.ustring()), DontDelete | ReadOnly | DontEnum);
 }
 
     : JSObject(structure)
 {
     putDirect(globalData->propertyNames->name, jsString(globalData, name.ustring()), DontDelete | ReadOnly | DontEnum);
 }
 
-const UString& InternalFunction::name(JSGlobalData* globalData)
+const UString& InternalFunction::name(ExecState* exec)
 {
 {
-    return asString(getDirect(globalData->propertyNames->name))->value();
+    return asString(getDirect(exec->globalData().propertyNames->name))->value(exec);
 }
 
 }
 
-const UString InternalFunction::displayName(JSGlobalData* globalData)
+const UString InternalFunction::displayName(ExecState* exec)
 {
 {
-    JSValue displayName = getDirect(globalData->propertyNames->displayName);
+    JSValue displayName = getDirect(exec->globalData().propertyNames->displayName);
     
     
-    if (displayName && isJSString(globalData, displayName))
-        return asString(displayName)->value();
+    if (displayName && isJSString(&exec->globalData(), displayName))
+        return asString(displayName)->value(exec);
     
     return UString::null();
 }
 
     
     return UString::null();
 }
 
-const UString InternalFunction::calculatedDisplayName(JSGlobalData* globalData)
+const UString InternalFunction::calculatedDisplayName(ExecState* exec)
 {
 {
-    const UString explicitName = displayName(globalData);
+    const UString explicitName = displayName(exec);
     
     if (!explicitName.isEmpty())
         return explicitName;
     
     
     if (!explicitName.isEmpty())
         return explicitName;
     
-    return name(globalData);
+    return name(exec);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 310644cedc05c8561504be40baf52cbd5ee59362..d19b82b38aae2332cf86420aa7b5a0308f309918 100644 (file)
@@ -36,18 +36,20 @@ namespace JSC {
         virtual const ClassInfo* classInfo() const; 
         static JS_EXPORTDATA const ClassInfo info;
 
         virtual const ClassInfo* classInfo() const; 
         static JS_EXPORTDATA const ClassInfo info;
 
-        const UString& name(JSGlobalData*);
-        const UString displayName(JSGlobalData*);
-        const UString calculatedDisplayName(JSGlobalData*);
+        const UString& name(ExecState*);
+        const UString displayName(ExecState*);
+        const UString calculatedDisplayName(ExecState*);
 
         static PassRefPtr<Structure> createStructure(JSValue proto) 
         { 
 
         static PassRefPtr<Structure> createStructure(JSValue proto) 
         { 
-            return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot)); 
+            return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
         }
 
     protected:
         }
 
     protected:
-        InternalFunction(PassRefPtr<Structure> structure) : JSObject(structure) { }
-        InternalFunction(JSGlobalData*, PassRefPtr<Structure>, const Identifier&);
+        static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
+
+        InternalFunction(NonNullPassRefPtr<Structure> structure) : JSObject(structure) { }
+        InternalFunction(JSGlobalData*, NonNullPassRefPtr<Structure>, const Identifier&);
 
     private:
         virtual CallType getCallData(CallData&) = 0;
 
     private:
         virtual CallType getCallData(CallData&) = 0;
index 475fad57ad00b51da42c3fc6e971c1d825b21fd8..e83724a1da19391ead6accbb8f0653e96c547327 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-JSValue JSAPIValueWrapper::toPrimitive(ExecState*, PreferredPrimitiveType) const
-{
-    ASSERT_NOT_REACHED();
-    return JSValue();
-}
-
-bool JSAPIValueWrapper::getPrimitiveNumber(ExecState*, double&, JSValue&)
-{
-    ASSERT_NOT_REACHED();
-    return false;
-}
-
-bool JSAPIValueWrapper::toBoolean(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return false;
-}
-
-double JSAPIValueWrapper::toNumber(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-
-UString JSAPIValueWrapper::toString(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return UString();
-}
-
-JSObject* JSAPIValueWrapper::toObject(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-
 } // namespace JSC
 } // namespace JSC
index e16fbbaf0ff4e78279cc1457469b8481277292f5..b5016c24230ededb5491b83220527d0a93ba0115 100644 (file)
@@ -26,6 +26,7 @@
 #include <wtf/Platform.h>
 
 #include "JSCell.h"
 #include <wtf/Platform.h>
 
 #include "JSCell.h"
+#include "CallFrame.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -36,18 +37,18 @@ namespace JSC {
 
         virtual bool isAPIValueWrapper() const { return true; }
 
 
         virtual bool isAPIValueWrapper() const { return true; }
 
-        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
-        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
-        virtual bool toBoolean(ExecState*) const;
-        virtual double toNumber(ExecState*) const;
-        virtual UString toString(ExecState*) const;
-        virtual JSObject* toObject(ExecState*) const;
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount);
+        }
 
 
+        
     private:
     private:
-        JSAPIValueWrapper(JSValue value)
-            : JSCell(0)
+        JSAPIValueWrapper(ExecState* exec, JSValue value)
+            : JSCell(exec->globalData().apiWrapperStructure.get())
             , m_value(value)
         {
             , m_value(value)
         {
+            ASSERT(!value.isCell());
         }
 
         JSValue m_value;
         }
 
         JSValue m_value;
@@ -55,7 +56,7 @@ namespace JSC {
 
     inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value)
     {
 
     inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value)
     {
-        return new (exec) JSAPIValueWrapper(value);
+        return new (exec) JSAPIValueWrapper(exec, value);
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index 33c84c2542b3f0dd7960e70807f7223d872cb9bc..22fdaafd46a1037327d53974366a65f44be28963 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -39,8 +39,8 @@ ASSERT_CLASS_FITS_IN_CELL(JSActivation);
 
 const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
 
 
 const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
 
-JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionBodyNode> functionBody)
-    : Base(callFrame->globalData().activationStructure, new JSActivationData(functionBody, callFrame->registers()))
+JSActivation::JSActivation(CallFrame* callFrame, NonNullPassRefPtr<FunctionExecutable> functionExecutable)
+    : Base(callFrame->globalData().activationStructure, new JSActivationData(functionExecutable, callFrame->registers()))
 {
 }
 
 {
 }
 
@@ -49,35 +49,23 @@ JSActivation::~JSActivation()
     delete d();
 }
 
     delete d();
 }
 
-void JSActivation::mark()
+void JSActivation::markChildren(MarkStack& markStack)
 {
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     Register* registerArray = d()->registerArray.get();
     if (!registerArray)
         return;
 
 
     Register* registerArray = d()->registerArray.get();
     if (!registerArray)
         return;
 
-    size_t numParametersMinusThis = d()->functionBody->parameterCount();
+    size_t numParametersMinusThis = d()->functionExecutable->parameterCount();
 
 
-    size_t i = 0;
-    size_t count = numParametersMinusThis; 
-    for ( ; i < count; ++i) {
-        Register& r = registerArray[i];
-        if (!r.marked())
-            r.mark();
-    }
+    size_t count = numParametersMinusThis;
+    markStack.appendValues(registerArray, count);
 
 
-    size_t numVars = d()->numVars;
+    size_t numVars = d()->functionExecutable->variableCount();
 
     // Skip the call frame, which sits between the parameters and vars.
 
     // Skip the call frame, which sits between the parameters and vars.
-    i += RegisterFile::CallFrameHeaderSize;
-    count += RegisterFile::CallFrameHeaderSize + numVars;
-
-    for ( ; i < count; ++i) {
-        Register& r = registerArray[i];
-        if (r.jsValue() && !r.marked())
-            r.mark();
-    }
+    markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues);
 }
 
 bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 }
 
 bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -148,14 +136,14 @@ JSObject* JSActivation::toThisObject(ExecState* exec) const
 
 bool JSActivation::isDynamicScope() const
 {
 
 bool JSActivation::isDynamicScope() const
 {
-    return d()->functionBody->usesEval();
+    return d()->functionExecutable->usesEval();
 }
 
 JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
 {
     JSActivation* activation = asActivation(slot.slotBase());
 
 }
 
 JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
 {
     JSActivation* activation = asActivation(slot.slotBase());
 
-    if (activation->d()->functionBody->usesArguments()) {
+    if (activation->d()->functionExecutable->usesArguments()) {
         PropertySlot slot;
         activation->symbolTableGet(exec->propertyNames().arguments, slot);
         return slot.getValue(exec, exec->propertyNames().arguments);
         PropertySlot slot;
         activation->symbolTableGet(exec->propertyNames().arguments, slot);
         return slot.getValue(exec, exec->propertyNames().arguments);
@@ -168,7 +156,7 @@ JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const
         arguments->copyRegisters();
         callFrame->setCalleeArguments(arguments);
     }
         arguments->copyRegisters();
         callFrame->setCalleeArguments(arguments);
     }
-    ASSERT(arguments->isObject(&Arguments::info));
+    ASSERT(arguments->inherits(&Arguments::info));
 
     return arguments;
 }
 
     return arguments;
 }
index e69aa6e6385826d84c079c5acdd2d4ff7f7510d2..761bee4a48109695db9ccddb45a74231643ad579 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -43,10 +43,10 @@ namespace JSC {
     class JSActivation : public JSVariableObject {
         typedef JSVariableObject Base;
     public:
     class JSActivation : public JSVariableObject {
         typedef JSVariableObject Base;
     public:
-        JSActivation(CallFrame*, PassRefPtr<FunctionBodyNode>);
+        JSActivation(CallFrame*, NonNullPassRefPtr<FunctionExecutable>);
         virtual ~JSActivation();
 
         virtual ~JSActivation();
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         virtual bool isDynamicScope() const;
 
 
         virtual bool isDynamicScope() const;
 
@@ -66,19 +66,27 @@ namespace JSC {
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
-        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); }
+        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
     private:
         struct JSActivationData : public JSVariableObjectData {
 
     private:
         struct JSActivationData : public JSVariableObjectData {
-            JSActivationData(PassRefPtr<FunctionBodyNode> _functionBody, Register* registers)
-                : JSVariableObjectData(&_functionBody->generatedBytecode().symbolTable(), registers)
-                , functionBody(_functionBody)
-                , numVars(functionBody->generatedBytecode().m_numVars)
+            JSActivationData(NonNullPassRefPtr<FunctionExecutable> _functionExecutable, Register* registers)
+                : JSVariableObjectData(_functionExecutable->generatedBytecode().symbolTable(), registers)
+                , functionExecutable(_functionExecutable)
+            {
+                // We have to manually ref and deref the symbol table as JSVariableObjectData
+                // doesn't know about SharedSymbolTable
+                functionExecutable->generatedBytecode().sharedSymbolTable()->ref();
+            }
+            ~JSActivationData()
             {
             {
+                static_cast<SharedSymbolTable*>(symbolTable)->deref();
             }
 
             }
 
-            RefPtr<FunctionBodyNode> functionBody;
-            size_t numVars;
+            RefPtr<FunctionExecutable> functionExecutable;
         };
         
         static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
         };
         
         static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
index 708ef99a27e3e878b780bda0eeedae2a67413fc0..2be73714425e037964cc4a3e019447d0abd98c79 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2003 Peter Kelly (pmk@post.com)
  *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
  *
  *  Copyright (C) 2003 Peter Kelly (pmk@post.com)
  *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
  *
@@ -25,6 +25,8 @@
 
 #include "ArrayPrototype.h"
 #include "CachedCall.h"
 
 #include "ArrayPrototype.h"
 #include "CachedCall.h"
+#include "Error.h"
+#include "Executable.h"
 #include "PropertyNameArray.h"
 #include <wtf/AVLTree.h>
 #include <wtf/Assertions.h>
 #include "PropertyNameArray.h"
 #include <wtf/AVLTree.h>
 #include <wtf/Assertions.h>
@@ -128,60 +130,57 @@ inline void JSArray::checkConsistency(ConsistencyCheckType)
 
 #endif
 
 
 #endif
 
-JSArray::JSArray(PassRefPtr<Structure> structure)
+JSArray::JSArray(NonNullPassRefPtr<Structure> structure)
     : JSObject(structure)
 {
     unsigned initialCapacity = 0;
 
     m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
     : JSObject(structure)
 {
     unsigned initialCapacity = 0;
 
     m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
-    m_storage->m_vectorLength = initialCapacity;
-
-    m_fastAccessCutoff = 0;
+    m_vectorLength = initialCapacity;
 
     checkConsistency();
 }
 
 
     checkConsistency();
 }
 
-JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength)
+JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength)
     : JSObject(structure)
 {
     unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX);
 
     m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
     m_storage->m_length = initialLength;
     : JSObject(structure)
 {
     unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX);
 
     m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
     m_storage->m_length = initialLength;
-    m_storage->m_vectorLength = initialCapacity;
+    m_vectorLength = initialCapacity;
     m_storage->m_numValuesInVector = 0;
     m_storage->m_sparseValueMap = 0;
     m_storage->lazyCreationData = 0;
     m_storage->m_numValuesInVector = 0;
     m_storage->m_sparseValueMap = 0;
     m_storage->lazyCreationData = 0;
+    m_storage->reportedMapCapacity = 0;
 
     JSValue* vector = m_storage->m_vector;
     for (size_t i = 0; i < initialCapacity; ++i)
         vector[i] = JSValue();
 
 
     JSValue* vector = m_storage->m_vector;
     for (size_t i = 0; i < initialCapacity; ++i)
         vector[i] = JSValue();
 
-    m_fastAccessCutoff = 0;
-
     checkConsistency();
 
     Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue));
 }
 
     checkConsistency();
 
     Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue));
 }
 
-JSArray::JSArray(PassRefPtr<Structure> structure, const ArgList& list)
+JSArray::JSArray(NonNullPassRefPtr<Structure> structure, const ArgList& list)
     : JSObject(structure)
 {
     unsigned initialCapacity = list.size();
 
     m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
     m_storage->m_length = initialCapacity;
     : JSObject(structure)
 {
     unsigned initialCapacity = list.size();
 
     m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
     m_storage->m_length = initialCapacity;
-    m_storage->m_vectorLength = initialCapacity;
+    m_vectorLength = initialCapacity;
     m_storage->m_numValuesInVector = initialCapacity;
     m_storage->m_sparseValueMap = 0;
     m_storage->m_numValuesInVector = initialCapacity;
     m_storage->m_sparseValueMap = 0;
+    m_storage->lazyCreationData = 0;
+    m_storage->reportedMapCapacity = 0;
 
     size_t i = 0;
     ArgList::const_iterator end = list.end();
     for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i)
         m_storage->m_vector[i] = *it;
 
 
     size_t i = 0;
     ArgList::const_iterator end = list.end();
     for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i)
         m_storage->m_vector[i] = *it;
 
-    m_fastAccessCutoff = initialCapacity;
-
     checkConsistency();
 
     Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity));
     checkConsistency();
 
     Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity));
@@ -189,6 +188,7 @@ JSArray::JSArray(PassRefPtr<Structure> structure, const ArgList& list)
 
 JSArray::~JSArray()
 {
 
 JSArray::~JSArray()
 {
+    ASSERT(vptr() == JSGlobalData::jsArrayVPtr);
     checkConsistency(DestructorConsistencyCheck);
 
     delete m_storage->m_sparseValueMap;
     checkConsistency(DestructorConsistencyCheck);
 
     delete m_storage->m_sparseValueMap;
@@ -205,7 +205,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot
         return false;
     }
 
         return false;
     }
 
-    if (i < storage->m_vectorLength) {
+    if (i < m_vectorLength) {
         JSValue& valueSlot = storage->m_vector[i];
         if (valueSlot) {
             slot.setValueSlot(&valueSlot);
         JSValue& valueSlot = storage->m_vector[i];
         if (valueSlot) {
             slot.setValueSlot(&valueSlot);
@@ -221,7 +221,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot
         }
     }
 
         }
     }
 
-    return false;
+    return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, i), slot);
 }
 
 bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 }
 
 bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -239,6 +239,37 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName
     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
+bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    if (propertyName == exec->propertyNames().length) {
+        descriptor.setDescriptor(jsNumber(exec, length()), DontDelete | DontEnum);
+        return true;
+    }
+    
+    bool isArrayIndex;
+    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    if (isArrayIndex) {
+        if (i >= m_storage->m_length)
+            return false;
+        if (i < m_vectorLength) {
+            JSValue& value = m_storage->m_vector[i];
+            if (value) {
+                descriptor.setDescriptor(value, 0);
+                return true;
+            }
+        } else if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
+            if (i >= MIN_SPARSE_ARRAY_INDEX) {
+                SparseArrayValueMap::iterator it = map->find(i);
+                if (it != map->end()) {
+                    descriptor.setDescriptor(it->second, 0);
+                    return true;
+                }
+            }
+        }
+    }
+    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
 // ECMA 15.4.5.1
 void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 // ECMA 15.4.5.1
 void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
@@ -272,7 +303,7 @@ void JSArray::put(ExecState* exec, unsigned i, JSValue value)
         m_storage->m_length = length;
     }
 
         m_storage->m_length = length;
     }
 
-    if (i < m_storage->m_vectorLength) {
+    if (i < m_vectorLength) {
         JSValue& valueSlot = m_storage->m_vector[i];
         if (valueSlot) {
             valueSlot = value;
         JSValue& valueSlot = m_storage->m_vector[i];
         if (valueSlot) {
             valueSlot = value;
@@ -280,8 +311,7 @@ void JSArray::put(ExecState* exec, unsigned i, JSValue value)
             return;
         }
         valueSlot = value;
             return;
         }
         valueSlot = value;
-        if (++m_storage->m_numValuesInVector == m_storage->m_length)
-            m_fastAccessCutoff = m_storage->m_length;
+        ++m_storage->m_numValuesInVector;
         checkConsistency();
         return;
     }
         checkConsistency();
         return;
     }
@@ -302,13 +332,24 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
         }
 
         // We miss some cases where we could compact the storage, such as a large array that is being filled from the end
         }
 
         // We miss some cases where we could compact the storage, such as a large array that is being filled from the end
-        // (which will only be compacted as we reach indices that are less than cutoff) - but this makes the check much faster.
+        // (which will only be compacted as we reach indices that are less than MIN_SPARSE_ARRAY_INDEX) - but this makes the check much faster.
         if ((i > MAX_STORAGE_VECTOR_INDEX) || !isDenseEnoughForVector(i + 1, storage->m_numValuesInVector + 1)) {
             if (!map) {
                 map = new SparseArrayValueMap;
                 storage->m_sparseValueMap = map;
             }
         if ((i > MAX_STORAGE_VECTOR_INDEX) || !isDenseEnoughForVector(i + 1, storage->m_numValuesInVector + 1)) {
             if (!map) {
                 map = new SparseArrayValueMap;
                 storage->m_sparseValueMap = map;
             }
-            map->set(i, value);
+
+            pair<SparseArrayValueMap::iterator, bool> result = map->add(i, value);
+            if (!result.second) { // pre-existing entry
+                result.first->second = value;
+                return;
+            }
+
+            size_t capacity = map->capacity();
+            if (capacity != storage->reportedMapCapacity) {
+                Heap::heap(this)->reportExtraMemoryCost((capacity - storage->reportedMapCapacity) * (sizeof(unsigned) + sizeof(JSValue)));
+                storage->reportedMapCapacity = capacity;
+            }
             return;
         }
     }
             return;
         }
     }
@@ -319,8 +360,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
         if (increaseVectorLength(i + 1)) {
             storage = m_storage;
             storage->m_vector[i] = value;
         if (increaseVectorLength(i + 1)) {
             storage = m_storage;
             storage->m_vector[i] = value;
-            if (++storage->m_numValuesInVector == storage->m_length)
-                m_fastAccessCutoff = storage->m_length;
+            ++storage->m_numValuesInVector;
             checkConsistency();
         } else
             throwOutOfMemoryError(exec);
             checkConsistency();
         } else
             throwOutOfMemoryError(exec);
@@ -330,7 +370,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
     // Decide how many values it would be best to move from the map.
     unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
     unsigned newVectorLength = increasedVectorLength(i + 1);
     // Decide how many values it would be best to move from the map.
     unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
     unsigned newVectorLength = increasedVectorLength(i + 1);
-    for (unsigned j = max(storage->m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
+    for (unsigned j = max(m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
         newNumValuesInVector += map->contains(j);
     if (i >= MIN_SPARSE_ARRAY_INDEX)
         newNumValuesInVector -= map->contains(i);
         newNumValuesInVector += map->contains(j);
     if (i >= MIN_SPARSE_ARRAY_INDEX)
         newNumValuesInVector -= map->contains(i);
@@ -348,15 +388,12 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
         }
     }
 
         }
     }
 
-    storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength)));
-    if (!storage) {
+    if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage)) {
         throwOutOfMemoryError(exec);
         return;
     }
 
         throwOutOfMemoryError(exec);
         return;
     }
 
-    unsigned vectorLength = storage->m_vectorLength;
-
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
+    unsigned vectorLength = m_vectorLength;
 
     if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
         for (unsigned j = vectorLength; j < newVectorLength; ++j)
 
     if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
         for (unsigned j = vectorLength; j < newVectorLength; ++j)
@@ -372,12 +409,14 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
 
     storage->m_vector[i] = value;
 
 
     storage->m_vector[i] = value;
 
-    storage->m_vectorLength = newVectorLength;
+    m_vectorLength = newVectorLength;
     storage->m_numValuesInVector = newNumValuesInVector;
 
     m_storage = storage;
 
     checkConsistency();
     storage->m_numValuesInVector = newNumValuesInVector;
 
     m_storage = storage;
 
     checkConsistency();
+
+    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
 }
 
 bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName)
 }
 
 bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName)
@@ -399,7 +438,7 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i)
 
     ArrayStorage* storage = m_storage;
 
 
     ArrayStorage* storage = m_storage;
 
-    if (i < storage->m_vectorLength) {
+    if (i < m_vectorLength) {
         JSValue& valueSlot = storage->m_vector[i];
         if (!valueSlot) {
             checkConsistency();
         JSValue& valueSlot = storage->m_vector[i];
         if (!valueSlot) {
             checkConsistency();
@@ -407,8 +446,6 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i)
         }
         valueSlot = JSValue();
         --storage->m_numValuesInVector;
         }
         valueSlot = JSValue();
         --storage->m_numValuesInVector;
-        if (m_fastAccessCutoff > i)
-            m_fastAccessCutoff = i;
         checkConsistency();
         return true;
     }
         checkConsistency();
         return true;
     }
@@ -432,7 +469,7 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i)
     return false;
 }
 
     return false;
 }
 
-void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     // FIXME: Filling PropertyNameArray with an identifier for every integer
     // is incredibly inefficient for large arrays. We need a different approach,
 {
     // FIXME: Filling PropertyNameArray with an identifier for every integer
     // is incredibly inefficient for large arrays. We need a different approach,
@@ -440,7 +477,7 @@ void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames
 
     ArrayStorage* storage = m_storage;
 
 
     ArrayStorage* storage = m_storage;
 
-    unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
+    unsigned usedVectorLength = min(storage->m_length, m_vectorLength);
     for (unsigned i = 0; i < usedVectorLength; ++i) {
         if (storage->m_vector[i])
             propertyNames.add(Identifier::from(exec, i));
     for (unsigned i = 0; i < usedVectorLength; ++i) {
         if (storage->m_vector[i])
             propertyNames.add(Identifier::from(exec, i));
@@ -452,7 +489,10 @@ void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames
             propertyNames.add(Identifier::from(exec, it->first));
     }
 
             propertyNames.add(Identifier::from(exec, it->first));
     }
 
-    JSObject::getPropertyNames(exec, propertyNames);
+    if (mode == IncludeDontEnumProperties)
+        propertyNames.add(exec->propertyNames().length);
+
+    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
 }
 
 bool JSArray::increaseVectorLength(unsigned newLength)
 }
 
 bool JSArray::increaseVectorLength(unsigned newLength)
@@ -462,22 +502,23 @@ bool JSArray::increaseVectorLength(unsigned newLength)
 
     ArrayStorage* storage = m_storage;
 
 
     ArrayStorage* storage = m_storage;
 
-    unsigned vectorLength = storage->m_vectorLength;
+    unsigned vectorLength = m_vectorLength;
     ASSERT(newLength > vectorLength);
     ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX);
     unsigned newVectorLength = increasedVectorLength(newLength);
 
     ASSERT(newLength > vectorLength);
     ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX);
     unsigned newVectorLength = increasedVectorLength(newLength);
 
-    storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength)));
-    if (!storage)
+    if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage))
         return false;
 
         return false;
 
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
-    storage->m_vectorLength = newVectorLength;
+    m_vectorLength = newVectorLength;
 
     for (unsigned i = vectorLength; i < newVectorLength; ++i)
         storage->m_vector[i] = JSValue();
 
     m_storage = storage;
 
     for (unsigned i = vectorLength; i < newVectorLength; ++i)
         storage->m_vector[i] = JSValue();
 
     m_storage = storage;
+
+    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
+
     return true;
 }
 
     return true;
 }
 
@@ -490,10 +531,7 @@ void JSArray::setLength(unsigned newLength)
     unsigned length = m_storage->m_length;
 
     if (newLength < length) {
     unsigned length = m_storage->m_length;
 
     if (newLength < length) {
-        if (m_fastAccessCutoff > newLength)
-            m_fastAccessCutoff = newLength;
-
-        unsigned usedVectorLength = min(length, storage->m_vectorLength);
+        unsigned usedVectorLength = min(length, m_vectorLength);
         for (unsigned i = newLength; i < usedVectorLength; ++i) {
             JSValue& valueSlot = storage->m_vector[i];
             bool hadValue = valueSlot;
         for (unsigned i = newLength; i < usedVectorLength; ++i) {
             JSValue& valueSlot = storage->m_vector[i];
             bool hadValue = valueSlot;
@@ -532,20 +570,13 @@ JSValue JSArray::pop()
 
     JSValue result;
 
 
     JSValue result;
 
-    if (m_fastAccessCutoff > length) {
-        JSValue& valueSlot = m_storage->m_vector[length];
-        result = valueSlot;
-        ASSERT(result);
-        valueSlot = JSValue();
-        --m_storage->m_numValuesInVector;
-        m_fastAccessCutoff = length;
-    } else if (length < m_storage->m_vectorLength) {
+    if (length < m_vectorLength) {
         JSValue& valueSlot = m_storage->m_vector[length];
         JSValue& valueSlot = m_storage->m_vector[length];
-        result = valueSlot;
-        valueSlot = JSValue();
-        if (result)
+        if (valueSlot) {
             --m_storage->m_numValuesInVector;
             --m_storage->m_numValuesInVector;
-        else
+            result = valueSlot;
+            valueSlot = JSValue();
+        } else
             result = jsUndefined();
     } else {
         result = jsUndefined();
             result = jsUndefined();
     } else {
         result = jsUndefined();
@@ -573,11 +604,10 @@ void JSArray::push(ExecState* exec, JSValue value)
 {
     checkConsistency();
 
 {
     checkConsistency();
 
-    if (m_storage->m_length < m_storage->m_vectorLength) {
-        ASSERT(!m_storage->m_vector[m_storage->m_length]);
+    if (m_storage->m_length < m_vectorLength) {
         m_storage->m_vector[m_storage->m_length] = value;
         m_storage->m_vector[m_storage->m_length] = value;
-        if (++m_storage->m_numValuesInVector == ++m_storage->m_length)
-            m_fastAccessCutoff = m_storage->m_length;
+        ++m_storage->m_numValuesInVector;
+        ++m_storage->m_length;
         checkConsistency();
         return;
     }
         checkConsistency();
         return;
     }
@@ -587,8 +617,8 @@ void JSArray::push(ExecState* exec, JSValue value)
         if (!map || map->isEmpty()) {
             if (increaseVectorLength(m_storage->m_length + 1)) {
                 m_storage->m_vector[m_storage->m_length] = value;
         if (!map || map->isEmpty()) {
             if (increaseVectorLength(m_storage->m_length + 1)) {
                 m_storage->m_vector[m_storage->m_length] = value;
-                if (++m_storage->m_numValuesInVector == ++m_storage->m_length)
-                    m_fastAccessCutoff = m_storage->m_length;
+                ++m_storage->m_numValuesInVector;
+                ++m_storage->m_length;
                 checkConsistency();
                 return;
             }
                 checkConsistency();
                 return;
             }
@@ -601,27 +631,9 @@ void JSArray::push(ExecState* exec, JSValue value)
     putSlowCase(exec, m_storage->m_length++, value);
 }
 
     putSlowCase(exec, m_storage->m_length++, value);
 }
 
-void JSArray::mark()
+void JSArray::markChildren(MarkStack& markStack)
 {
 {
-    JSObject::mark();
-
-    ArrayStorage* storage = m_storage;
-
-    unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
-    for (unsigned i = 0; i < usedVectorLength; ++i) {
-        JSValue value = storage->m_vector[i];
-        if (value && !value.marked())
-            value.mark();
-    }
-
-    if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
-        SparseArrayValueMap::iterator end = map->end();
-        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
-            JSValue value = it->second;
-            if (!value.marked())
-                value.mark();
-        }
-    }
+    markChildrenDirect(markStack);
 }
 
 static int compareNumbersForQSort(const void* a, const void* b)
 }
 
 static int compareNumbersForQSort(const void* a, const void* b)
@@ -793,7 +805,7 @@ struct AVLTreeAbstractorForArrayCompare {
             m_cachedCall->setThis(m_globalThisValue);
             m_cachedCall->setArgument(0, va);
             m_cachedCall->setArgument(1, vb);
             m_cachedCall->setThis(m_globalThisValue);
             m_cachedCall->setArgument(0, va);
             m_cachedCall->setArgument(1, vb);
-            compareResult = m_cachedCall->call().toNumber(m_cachedCall->newCallFrame());
+            compareResult = m_cachedCall->call().toNumber(m_cachedCall->newCallFrame(m_exec));
         } else {
             MarkedArgumentBuffer arguments;
             arguments.append(va);
         } else {
             MarkedArgumentBuffer arguments;
             arguments.append(va);
@@ -824,7 +836,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
     if (!m_storage->m_length)
         return;
 
     if (!m_storage->m_length)
         return;
 
-    unsigned usedVectorLength = min(m_storage->m_length, m_storage->m_vectorLength);
+    unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength);
 
     AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items
     tree.abstractor().m_exec = exec;
 
     AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items
     tree.abstractor().m_exec = exec;
@@ -873,7 +885,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
 
     if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
         newUsedVectorLength += map->size();
 
     if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
         newUsedVectorLength += map->size();
-        if (newUsedVectorLength > m_storage->m_vectorLength) {
+        if (newUsedVectorLength > m_vectorLength) {
             // Check that it is possible to allocate an array large enough to hold all the entries.
             if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) {
                 throwOutOfMemoryError(exec);
             // Check that it is possible to allocate an array large enough to hold all the entries.
             if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) {
                 throwOutOfMemoryError(exec);
@@ -913,7 +925,6 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
     for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
         m_storage->m_vector[i] = JSValue();
 
     for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
         m_storage->m_vector[i] = JSValue();
 
-    m_fastAccessCutoff = newUsedVectorLength;
     m_storage->m_numValuesInVector = newUsedVectorLength;
 
     checkConsistency(SortConsistencyCheck);
     m_storage->m_numValuesInVector = newUsedVectorLength;
 
     checkConsistency(SortConsistencyCheck);
@@ -921,10 +932,16 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
 
 void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
 {
 
 void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
 {
-    unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);
+    JSValue* vector = m_storage->m_vector;
+    unsigned vectorEnd = min(m_storage->m_length, m_vectorLength);
     unsigned i = 0;
     unsigned i = 0;
-    for (; i < fastAccessLength; ++i)
-        args.append(getIndex(i));
+    for (; i < vectorEnd; ++i) {
+        JSValue& v = vector[i];
+        if (!v)
+            break;
+        args.append(v);
+    }
+
     for (; i < m_storage->m_length; ++i)
         args.append(get(exec, i));
 }
     for (; i < m_storage->m_length; ++i)
         args.append(get(exec, i));
 }
@@ -933,12 +950,17 @@ void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSiz
 {
     ASSERT(m_storage->m_length == maxSize);
     UNUSED_PARAM(maxSize);
 {
     ASSERT(m_storage->m_length == maxSize);
     UNUSED_PARAM(maxSize);
-    unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);
+    JSValue* vector = m_storage->m_vector;
+    unsigned vectorEnd = min(m_storage->m_length, m_vectorLength);
     unsigned i = 0;
     unsigned i = 0;
-    for (; i < fastAccessLength; ++i)
-        buffer[i] = getIndex(i);
-    uint32_t size = m_storage->m_length;
-    for (; i < size; ++i)
+    for (; i < vectorEnd; ++i) {
+        JSValue& v = vector[i];
+        if (!v)
+            break;
+        buffer[i] = v;
+    }
+
+    for (; i < m_storage->m_length; ++i)
         buffer[i] = get(exec, i);
 }
 
         buffer[i] = get(exec, i);
 }
 
@@ -948,7 +970,7 @@ unsigned JSArray::compactForSorting()
 
     ArrayStorage* storage = m_storage;
 
 
     ArrayStorage* storage = m_storage;
 
-    unsigned usedVectorLength = min(m_storage->m_length, storage->m_vectorLength);
+    unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength);
 
     unsigned numDefined = 0;
     unsigned numUndefined = 0;
 
     unsigned numDefined = 0;
     unsigned numUndefined = 0;
@@ -972,7 +994,7 @@ unsigned JSArray::compactForSorting()
 
     if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
         newUsedVectorLength += map->size();
 
     if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
         newUsedVectorLength += map->size();
-        if (newUsedVectorLength > storage->m_vectorLength) {
+        if (newUsedVectorLength > m_vectorLength) {
             // Check that it is possible to allocate an array large enough to hold all the entries - if not,
             // exception is thrown by caller.
             if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength))
             // Check that it is possible to allocate an array large enough to hold all the entries - if not,
             // exception is thrown by caller.
             if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength))
@@ -993,7 +1015,6 @@ unsigned JSArray::compactForSorting()
     for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
         storage->m_vector[i] = JSValue();
 
     for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
         storage->m_vector[i] = JSValue();
 
-    m_fastAccessCutoff = newUsedVectorLength;
     storage->m_numValuesInVector = newUsedVectorLength;
 
     checkConsistency(SortConsistencyCheck);
     storage->m_numValuesInVector = newUsedVectorLength;
 
     checkConsistency(SortConsistencyCheck);
@@ -1019,30 +1040,27 @@ void JSArray::checkConsistency(ConsistencyCheckType type)
     if (type == SortConsistencyCheck)
         ASSERT(!m_storage->m_sparseValueMap);
 
     if (type == SortConsistencyCheck)
         ASSERT(!m_storage->m_sparseValueMap);
 
-    ASSERT(m_fastAccessCutoff <= m_storage->m_length);
-    ASSERT(m_fastAccessCutoff <= m_storage->m_numValuesInVector);
-
     unsigned numValuesInVector = 0;
     unsigned numValuesInVector = 0;
-    for (unsigned i = 0; i < m_storage->m_vectorLength; ++i) {
+    for (unsigned i = 0; i < m_vectorLength; ++i) {
         if (JSValue value = m_storage->m_vector[i]) {
             ASSERT(i < m_storage->m_length);
             if (type != DestructorConsistencyCheck)
                 value->type(); // Likely to crash if the object was deallocated.
             ++numValuesInVector;
         } else {
         if (JSValue value = m_storage->m_vector[i]) {
             ASSERT(i < m_storage->m_length);
             if (type != DestructorConsistencyCheck)
                 value->type(); // Likely to crash if the object was deallocated.
             ++numValuesInVector;
         } else {
-            ASSERT(i >= m_fastAccessCutoff);
             if (type == SortConsistencyCheck)
                 ASSERT(i >= m_storage->m_numValuesInVector);
         }
     }
     ASSERT(numValuesInVector == m_storage->m_numValuesInVector);
             if (type == SortConsistencyCheck)
                 ASSERT(i >= m_storage->m_numValuesInVector);
         }
     }
     ASSERT(numValuesInVector == m_storage->m_numValuesInVector);
+    ASSERT(numValuesInVector <= m_storage->m_length);
 
     if (m_storage->m_sparseValueMap) {
         SparseArrayValueMap::iterator end = m_storage->m_sparseValueMap->end();
         for (SparseArrayValueMap::iterator it = m_storage->m_sparseValueMap->begin(); it != end; ++it) {
             unsigned index = it->first;
             ASSERT(index < m_storage->m_length);
 
     if (m_storage->m_sparseValueMap) {
         SparseArrayValueMap::iterator end = m_storage->m_sparseValueMap->end();
         for (SparseArrayValueMap::iterator it = m_storage->m_sparseValueMap->begin(); it != end; ++it) {
             unsigned index = it->first;
             ASSERT(index < m_storage->m_length);
-            ASSERT(index >= m_storage->m_vectorLength);
+            ASSERT(index >= m_vectorLength);
             ASSERT(index <= MAX_ARRAY_INDEX);
             ASSERT(it->second);
             if (type != DestructorConsistencyCheck)
             ASSERT(index <= MAX_ARRAY_INDEX);
             ASSERT(it->second);
             if (type != DestructorConsistencyCheck)
@@ -1053,26 +1071,4 @@ void JSArray::checkConsistency(ConsistencyCheckType type)
 
 #endif
 
 
 #endif
 
-JSArray* constructEmptyArray(ExecState* exec)
-{
-    return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());
-}
-
-JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
-{
-    return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength);
-}
-
-JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
-{
-    MarkedArgumentBuffer values;
-    values.append(singleItemValue);
-    return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
-}
-
-JSArray* constructArray(ExecState* exec, const ArgList& values)
-{
-    return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
-}
-
 } // namespace JSC
 } // namespace JSC
index ea490d86aa4c2dee468f1f408d857fc2b6eca998..ad6ee88c92e0bb504652cd81e7d248548c7eb89b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -29,24 +29,26 @@ namespace JSC {
 
     struct ArrayStorage {
         unsigned m_length;
 
     struct ArrayStorage {
         unsigned m_length;
-        unsigned m_vectorLength;
         unsigned m_numValuesInVector;
         SparseArrayValueMap* m_sparseValueMap;
         void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily.
         unsigned m_numValuesInVector;
         SparseArrayValueMap* m_sparseValueMap;
         void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily.
+        size_t reportedMapCapacity;
         JSValue m_vector[1];
     };
 
     class JSArray : public JSObject {
         friend class JIT;
         JSValue m_vector[1];
     };
 
     class JSArray : public JSObject {
         friend class JIT;
+        friend class Walker;
 
     public:
 
     public:
-        explicit JSArray(PassRefPtr<Structure>);
-        JSArray(PassRefPtr<Structure>, unsigned initialLength);
-        JSArray(PassRefPtr<Structure>, const ArgList& initialValues);
+        explicit JSArray(NonNullPassRefPtr<Structure>);
+        JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength);
+        JSArray(NonNullPassRefPtr<Structure>, const ArgList& initialValues);
         virtual ~JSArray();
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
         virtual ~JSArray();
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
         virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem.
 
         static JS_EXPORTDATA const ClassInfo info;
         virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem.
 
         static JS_EXPORTDATA const ClassInfo info;
@@ -61,18 +63,24 @@ namespace JSC {
         void push(ExecState*, JSValue);
         JSValue pop();
 
         void push(ExecState*, JSValue);
         JSValue pop();
 
-        bool canGetIndex(unsigned i) { return i < m_fastAccessCutoff; }
+        bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
         JSValue getIndex(unsigned i)
         {
             ASSERT(canGetIndex(i));
             return m_storage->m_vector[i];
         }
 
         JSValue getIndex(unsigned i)
         {
             ASSERT(canGetIndex(i));
             return m_storage->m_vector[i];
         }
 
-        bool canSetIndex(unsigned i) { return i < m_fastAccessCutoff; }
-        JSValue setIndex(unsigned i, JSValue v)
+        bool canSetIndex(unsigned i) { return i < m_vectorLength; }
+        void setIndex(unsigned i, JSValue v)
         {
             ASSERT(canSetIndex(i));
         {
             ASSERT(canSetIndex(i));
-            return m_storage->m_vector[i] = v;
+            JSValue& x = m_storage->m_vector[i];
+            if (!x) {
+                ++m_storage->m_numValuesInVector;
+                if (i >= m_storage->m_length)
+                    m_storage->m_length = i + 1;
+            }
+            x = v;
         }
 
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
         }
 
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
@@ -80,15 +88,18 @@ namespace JSC {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType));
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
         }
+        
+        inline void markChildrenDirect(MarkStack& markStack);
 
     protected:
 
     protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
         virtual bool deleteProperty(ExecState*, unsigned propertyName);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
         virtual bool deleteProperty(ExecState*, unsigned propertyName);
-        virtual void getPropertyNames(ExecState*, PropertyNameArray&);
-        virtual void mark();
+        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+        virtual void markChildren(MarkStack&);
 
         void* lazyCreationData();
         void setLazyCreationData(void*);
 
         void* lazyCreationData();
         void setLazyCreationData(void*);
@@ -106,25 +117,110 @@ namespace JSC {
         enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
         void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
 
         enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
         void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
 
-        unsigned m_fastAccessCutoff;
+        unsigned m_vectorLength;
         ArrayStorage* m_storage;
     };
 
     JSArray* asArray(JSValue);
 
         ArrayStorage* m_storage;
     };
 
     JSArray* asArray(JSValue);
 
-    JSArray* constructEmptyArray(ExecState*);
-    JSArray* constructEmptyArray(ExecState*, unsigned initialLength);
-    JSArray* constructArray(ExecState*, JSValue singleItemValue);
-    JSArray* constructArray(ExecState*, const ArgList& values);
+    inline JSArray* asArray(JSCell* cell)
+    {
+        ASSERT(cell->inherits(&JSArray::info));
+        return static_cast<JSArray*>(cell);
+    }
 
     inline JSArray* asArray(JSValue value)
     {
 
     inline JSArray* asArray(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&JSArray::info));
-        return static_cast<JSArray*>(asObject(value));
+        return asArray(value.asCell());
+    }
+
+    inline bool isJSArray(JSGlobalData* globalData, JSValue v)
+    {
+        return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr;
+    }
+    inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; }
+
+    inline void JSArray::markChildrenDirect(MarkStack& markStack)
+    {
+        JSObject::markChildrenDirect(markStack);
+        
+        ArrayStorage* storage = m_storage;
+
+        unsigned usedVectorLength = std::min(storage->m_length, m_vectorLength);
+        markStack.appendValues(storage->m_vector, usedVectorLength, MayContainNullValues);
+
+        if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+            SparseArrayValueMap::iterator end = map->end();
+            for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
+                markStack.append(it->second);
+        }
     }
 
     }
 
-    inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr; }
+    inline void MarkStack::markChildren(JSCell* cell)
+    {
+        ASSERT(Heap::isCellMarked(cell));
+        if (!cell->structure()->typeInfo().overridesMarkChildren()) {
+#ifdef NDEBUG
+            asObject(cell)->markChildrenDirect(*this);
+#else
+            ASSERT(!m_isCheckingForDefaultMarkViolation);
+            m_isCheckingForDefaultMarkViolation = true;
+            cell->markChildren(*this);
+            ASSERT(m_isCheckingForDefaultMarkViolation);
+            m_isCheckingForDefaultMarkViolation = false;
+#endif
+            return;
+        }
+        if (cell->vptr() == m_jsArrayVPtr) {
+            asArray(cell)->markChildrenDirect(*this);
+            return;
+        }
+        cell->markChildren(*this);
+    }
 
 
+    inline void MarkStack::drain()
+    {
+        while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
+            while (!m_markSets.isEmpty() && m_values.size() < 50) {
+                ASSERT(!m_markSets.isEmpty());
+                MarkSet& current = m_markSets.last();
+                ASSERT(current.m_values);
+                JSValue* end = current.m_end;
+                ASSERT(current.m_values);
+                ASSERT(current.m_values != end);
+            findNextUnmarkedNullValue:
+                ASSERT(current.m_values != end);
+                JSValue value = *current.m_values;
+                current.m_values++;
+
+                JSCell* cell;
+                if (!value || !value.isCell() || Heap::isCellMarked(cell = value.asCell())) {
+                    if (current.m_values == end) {
+                        m_markSets.removeLast();
+                        continue;
+                    }
+                    goto findNextUnmarkedNullValue;
+                }
+
+                Heap::markCell(cell);
+                if (cell->structure()->typeInfo().type() < CompoundType) {
+                    if (current.m_values == end) {
+                        m_markSets.removeLast();
+                        continue;
+                    }
+                    goto findNextUnmarkedNullValue;
+                }
+
+                if (current.m_values == end)
+                    m_markSets.removeLast();
+
+                markChildren(cell);
+            }
+            while (!m_values.isEmpty())
+                markChildren(m_values.removeLast());
+        }
+    }
+    
 } // namespace JSC
 
 #endif // JSArray_h
 } // namespace JSC
 
 #endif // JSArray_h
index 2a5e72f74c69e7e7a0b6b55dd853b2126997a3d2..803a08c97c23100f640c6904dbc04d3719de8d60 100644 (file)
@@ -35,17 +35,25 @@ namespace JSC {
 
 const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", 0, 0, 0 };
 
 
 const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", 0, 0, 0 };
 
-JSByteArray::JSByteArray(ExecState* exec, PassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo)
+JSByteArray::JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo)
     : JSObject(structure)
     , m_storage(storage)
     , m_classInfo(classInfo)
 {
     putDirect(exec->globalData().propertyNames->length, jsNumber(exec, m_storage->length()), ReadOnly | DontDelete);
 }
     : JSObject(structure)
     , m_storage(storage)
     , m_classInfo(classInfo)
 {
     putDirect(exec->globalData().propertyNames->length, jsNumber(exec, m_storage->length()), ReadOnly | DontDelete);
 }
-    
+
+#if !ASSERT_DISABLED
+JSByteArray::~JSByteArray()
+{
+    ASSERT(vptr() == JSGlobalData::jsByteArrayVPtr);
+}
+#endif
+
+
 PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype)
 {
 PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype)
 {
-    PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType));
+    PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
     return result;
 }
 
     return result;
 }
 
@@ -59,7 +67,18 @@ bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& property
     }
     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
 }
     }
     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
 }
-    
+
+bool JSByteArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    bool ok;
+    unsigned index = propertyName.toUInt32(&ok, false);
+    if (ok && canAccessIndex(index)) {
+        descriptor.setDescriptor(getIndex(exec, index), DontDelete);
+        return true;
+    }
+    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
 bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
 {
     if (canAccessIndex(propertyName)) {
 bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
 {
     if (canAccessIndex(propertyName)) {
@@ -85,12 +104,12 @@ void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValue value)
     setIndex(exec, propertyName, value);
 }
 
     setIndex(exec, propertyName, value);
 }
 
-void JSByteArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSByteArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     unsigned length = m_storage->length();
     for (unsigned i = 0; i < length; ++i)
         propertyNames.add(Identifier::from(exec, i));
 {
     unsigned length = m_storage->length();
     for (unsigned i = 0; i < length; ++i)
         propertyNames.add(Identifier::from(exec, i));
-    JSObject::getPropertyNames(exec, propertyNames);
+    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
 }
 
 }
 }
 
 }
index 57374e0ace608361ea14d8a40f7b7c7f578fcce5..5b7adcf88841da9f98e0534ecfa527fd867d1053 100644 (file)
@@ -33,7 +33,7 @@
 namespace JSC {
 
     class JSByteArray : public JSObject {
 namespace JSC {
 
     class JSByteArray : public JSObject {
-        friend class VPtrSet;
+        friend class JSGlobalData;
     public:
         bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
         JSValue getIndex(ExecState* exec, unsigned i)
     public:
         bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
         JSValue getIndex(ExecState* exec, unsigned i)
@@ -73,15 +73,16 @@ namespace JSC {
                 setIndex(i, byteValue);
         }
 
                 setIndex(i, byteValue);
         }
 
-        JSByteArray(ExecState* exec, PassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo);
+        JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo);
         static PassRefPtr<Structure> createStructure(JSValue prototype);
         
         virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
         virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
         static PassRefPtr<Structure> createStructure(JSValue prototype);
         
         virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
         virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
         virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
         virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);
 
         virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
         virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);
 
-        virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
+        virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
 
         virtual const ClassInfo* classInfo() const { return m_classInfo; }
         static const ClassInfo s_defaultInfo;
 
         virtual const ClassInfo* classInfo() const { return m_classInfo; }
         static const ClassInfo s_defaultInfo;
@@ -90,6 +91,13 @@ namespace JSC {
 
         WTF::ByteArray* storage() const { return m_storage.get(); }
 
 
         WTF::ByteArray* storage() const { return m_storage.get(); }
 
+#if !ASSERT_DISABLED
+        virtual ~JSByteArray();
+#endif
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
+
     private:
         enum VPtrStealingHackType { VPtrStealingHack };
         JSByteArray(VPtrStealingHackType) 
     private:
         enum VPtrStealingHackType { VPtrStealingHack };
         JSByteArray(VPtrStealingHackType) 
index c733ed90783b1e8e1fbad55ae7231f3abbdd4f30..869fbfc883e0ab2bd0d0a859090a02e43c2a36cf 100644 (file)
@@ -59,10 +59,10 @@ static const union {
     } doubles;
     
 } NaNInf = { {
     } doubles;
     
 } NaNInf = { {
-#if PLATFORM(BIG_ENDIAN)
+#if CPU(BIG_ENDIAN)
     { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 },
     { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
     { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 },
     { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
-#elif PLATFORM(MIDDLE_ENDIAN)
+#elif CPU(MIDDLE_ENDIAN)
     { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 },
     { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 }
 #else
     { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 },
     { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 }
 #else
@@ -76,36 +76,27 @@ extern const double Inf = NaNInf.doubles.Inf_Double;
  
 #endif // !(defined NAN && defined INFINITY)
 
  
 #endif // !(defined NAN && defined INFINITY)
 
-void* JSCell::operator new(size_t size, ExecState* exec)
-{
-#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
-    return exec->heap()->inlineAllocate(size);
-#else
-    return exec->heap()->allocate(size);
-#endif
-}
-
 bool JSCell::getUInt32(uint32_t&) const
 {
     return false;
 }
 
 bool JSCell::getUInt32(uint32_t&) const
 {
     return false;
 }
 
-bool JSCell::getString(UString&stringValue) const
+bool JSCell::getString(ExecState* exec, UString&stringValue) const
 {
     if (!isString())
         return false;
 {
     if (!isString())
         return false;
-    stringValue = static_cast<const JSString*>(this)->value();
+    stringValue = static_cast<const JSString*>(this)->value(exec);
     return true;
 }
 
     return true;
 }
 
-UString JSCell::getString() const
+UString JSCell::getString(ExecState* exec) const
 {
 {
-    return isString() ? static_cast<const JSString*>(this)->value() : UString();
+    return isString() ? static_cast<const JSString*>(this)->value(exec) : UString();
 }
 
 JSObject* JSCell::getObject()
 {
 }
 
 JSObject* JSCell::getObject()
 {
-    return isObject() ? static_cast<JSObject*>(this) : 0;
+    return isObject() ? asObject(this) : 0;
 }
 
 const JSObject* JSCell::getObject() const
 }
 
 const JSObject* JSCell::getObject() const
@@ -197,4 +188,40 @@ bool JSCell::isGetterSetter() const
     return false;
 }
 
     return false;
 }
 
+JSValue JSCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+    ASSERT_NOT_REACHED();
+    return JSValue();
+}
+
+bool JSCell::getPrimitiveNumber(ExecState*, double&, JSValue&)
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool JSCell::toBoolean(ExecState*) const
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+double JSCell::toNumber(ExecState*) const
+{
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+UString JSCell::toString(ExecState*) const
+{
+    ASSERT_NOT_REACHED();
+    return UString();
+}
+
+JSObject* JSCell::toObject(ExecState*) const
+{
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
 } // namespace JSC
 } // namespace JSC
index 2cb5959a1571005c88223952681d98c1e50111ca..3c8c82910274a7dd4522a55ba68401eb2f852cdb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 #ifndef JSCell_h
 #define JSCell_h
 
 #ifndef JSCell_h
 #define JSCell_h
 
-#include <wtf/Noncopyable.h>
-#include "Structure.h"
-#include "JSValue.h"
-#include "JSImmediate.h"
 #include "Collector.h"
 #include "Collector.h"
+#include "JSImmediate.h"
+#include "JSValue.h"
+#include "MarkStack.h"
+#include "Structure.h"
+#include <wtf/Noncopyable.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class JSCell : Noncopyable {
+    class JSCell : public NoncopyableCustomAllocated {
         friend class GetterSetter;
         friend class Heap;
         friend class JIT;
         friend class GetterSetter;
         friend class Heap;
         friend class JIT;
@@ -41,13 +42,19 @@ namespace JSC {
         friend class JSString;
         friend class JSValue;
         friend class JSAPIValueWrapper;
         friend class JSString;
         friend class JSValue;
         friend class JSAPIValueWrapper;
-        friend struct VPtrSet;
+        friend class JSZombie;
+        friend class JSGlobalData;
 
     private:
         explicit JSCell(Structure*);
         virtual ~JSCell();
 
     public:
 
     private:
         explicit JSCell(Structure*);
         virtual ~JSCell();
 
     public:
+        static PassRefPtr<Structure> createDummyStructure()
+        {
+            return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount);
+        }
+
         // Querying the type.
 #if USE(JSVALUE32)
         bool isNumber() const;
         // Querying the type.
 #if USE(JSVALUE32)
         bool isNumber() const;
@@ -55,14 +62,15 @@ namespace JSC {
         bool isString() const;
         bool isObject() const;
         virtual bool isGetterSetter() const;
         bool isString() const;
         bool isObject() const;
         virtual bool isGetterSetter() const;
-        virtual bool isObject(const ClassInfo*) const;
+        bool inherits(const ClassInfo*) const;
         virtual bool isAPIValueWrapper() const { return false; }
         virtual bool isAPIValueWrapper() const { return false; }
+        virtual bool isPropertyNameIterator() const { return false; }
 
         Structure* structure() const;
 
         // Extracting the value.
 
         Structure* structure() const;
 
         // Extracting the value.
-        bool getString(UString&) const;
-        UString getString() const; // null string if not a string
+        bool getString(ExecState* exec, UString&) const;
+        UString getString(ExecState* exec) const; // null string if not a string
         JSObject* getObject(); // NULL if not an object
         const JSObject* getObject() const; // NULL if not an object
         
         JSObject* getObject(); // NULL if not an object
         const JSObject* getObject() const; // NULL if not an object
         
@@ -74,19 +82,22 @@ namespace JSC {
         virtual bool getUInt32(uint32_t&) const;
 
         // Basic conversions.
         virtual bool getUInt32(uint32_t&) const;
 
         // Basic conversions.
-        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
-        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&) = 0;
-        virtual bool toBoolean(ExecState*) const = 0;
-        virtual double toNumber(ExecState*) const = 0;
-        virtual UString toString(ExecState*) const = 0;
-        virtual JSObject* toObject(ExecState*) const = 0;
+        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
+        virtual bool toBoolean(ExecState*) const;
+        virtual double toNumber(ExecState*) const;
+        virtual UString toString(ExecState*) const;
+        virtual JSObject* toObject(ExecState*) const;
 
         // Garbage collection.
         void* operator new(size_t, ExecState*);
         void* operator new(size_t, JSGlobalData*);
         void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
 
         // Garbage collection.
         void* operator new(size_t, ExecState*);
         void* operator new(size_t, JSGlobalData*);
         void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
-        virtual void mark();
-        bool marked() const;
+
+        virtual void markChildren(MarkStack&);
+#if ENABLE(JSC_ZOMBIES)
+        virtual bool isZombie() const { return false; }
+#endif
 
         // Object operations, with the toObject operation included.
         virtual const ClassInfo* classInfo() const;
 
         // Object operations, with the toObject operation included.
         virtual const ClassInfo* classInfo() const;
@@ -100,6 +111,10 @@ namespace JSC {
         virtual JSString* toThisJSString(ExecState*);
         virtual JSValue getJSNumber();
         void* vptr() { return *reinterpret_cast<void**>(this); }
         virtual JSString* toThisJSString(ExecState*);
         virtual JSValue getJSNumber();
         void* vptr() { return *reinterpret_cast<void**>(this); }
+        void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; }
+
+    protected:
+        static const unsigned AnonymousSlotCount = 0;
 
     private:
         // Base implementation; for non-object classes implements getPropertySlot.
 
     private:
         // Base implementation; for non-object classes implements getPropertySlot.
@@ -110,13 +125,6 @@ namespace JSC {
         Structure* m_structure;
     };
 
         Structure* m_structure;
     };
 
-    JSCell* asCell(JSValue);
-
-    inline JSCell* asCell(JSValue value)
-    {
-        return value.asCell();
-    }
-
     inline JSCell::JSCell(Structure* structure)
         : m_structure(structure)
     {
     inline JSCell::JSCell(Structure* structure)
         : m_structure(structure)
     {
@@ -129,7 +137,7 @@ namespace JSC {
 #if USE(JSVALUE32)
     inline bool JSCell::isNumber() const
     {
 #if USE(JSVALUE32)
     inline bool JSCell::isNumber() const
     {
-        return Heap::isNumber(const_cast<JSCell*>(this));
+        return m_structure->typeInfo().type() == NumberType;
     }
 #endif
 
     }
 #endif
 
@@ -148,23 +156,18 @@ namespace JSC {
         return m_structure;
     }
 
         return m_structure;
     }
 
-    inline bool JSCell::marked() const
+    inline void JSCell::markChildren(MarkStack&)
     {
     {
-        return Heap::isCellMarked(this);
     }
 
     }
 
-    inline void JSCell::mark()
+    inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
     {
     {
-        return Heap::markCell(this);
+        return globalData->heap.allocate(size);
     }
 
     }
 
-    inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
+    inline void* JSCell::operator new(size_t size, ExecState* exec)
     {
     {
-#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
-        return globalData->heap.inlineAllocate(size);
-#else
-        return globalData->heap.allocate(size);
-#endif
+        return exec->heap()->allocate(size);
     }
 
     // --- JSValue inlines ----------------------------
     }
 
     // --- JSValue inlines ----------------------------
@@ -184,14 +187,14 @@ namespace JSC {
         return isCell() && asCell()->isObject();
     }
 
         return isCell() && asCell()->isObject();
     }
 
-    inline bool JSValue::getString(UString& s) const
+    inline bool JSValue::getString(ExecState* exec, UString& s) const
     {
     {
-        return isCell() && asCell()->getString(s);
+        return isCell() && asCell()->getString(exec, s);
     }
 
     }
 
-    inline UString JSValue::getString() const
+    inline UString JSValue::getString(ExecState* exec) const
     {
     {
-        return isCell() ? asCell()->getString() : UString();
+        return isCell() ? asCell()->getString(exec) : UString();
     }
 
     inline JSObject* JSValue::getObject() const
     }
 
     inline JSObject* JSValue::getObject() const
@@ -224,16 +227,6 @@ namespace JSC {
         return false;
     }
 
         return false;
     }
 
-    inline void JSValue::mark()
-    {
-        asCell()->mark(); // callers should check !marked() before calling mark(), so this should only be called with cells
-    }
-
-    inline bool JSValue::marked() const
-    {
-        return !isCell() || asCell()->marked();
-    }
-
 #if !USE(JSVALUE32_64)
     ALWAYS_INLINE JSCell* JSValue::asCell() const
     {
 #if !USE(JSVALUE32_64)
     ALWAYS_INLINE JSCell* JSValue::asCell() const
     {
@@ -301,24 +294,6 @@ namespace JSC {
         return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0.
     }
 
         return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0.
     }
 
-    inline UString JSValue::toString(ExecState* exec) const
-    {
-        if (isCell())
-            return asCell()->toString(exec);
-        if (isInt32())
-            return UString::from(asInt32());
-        if (isDouble())
-            return asDouble() == 0.0 ? "0" : UString::from(asDouble());
-        if (isTrue())
-            return "true";
-        if (isFalse())
-            return "false";
-        if (isNull())
-            return "null";
-        ASSERT(isUndefined());
-        return "undefined";
-    }
-
     inline bool JSValue::needsThisConversion() const
     {
         if (UNLIKELY(!isCell()))
     inline bool JSValue::needsThisConversion() const
     {
         if (UNLIKELY(!isCell()))
@@ -350,6 +325,42 @@ namespace JSC {
         return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
     }
 
         return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
     }
 
+    ALWAYS_INLINE void MarkStack::append(JSCell* cell)
+    {
+        ASSERT(!m_isCheckingForDefaultMarkViolation);
+        ASSERT(cell);
+        if (Heap::isCellMarked(cell))
+            return;
+        Heap::markCell(cell);
+        if (cell->structure()->typeInfo().type() >= CompoundType)
+            m_values.append(cell);
+    }
+
+    ALWAYS_INLINE void MarkStack::append(JSValue value)
+    {
+        ASSERT(value);
+        if (value.isCell())
+            append(value.asCell());
+    }
+
+    inline Heap* Heap::heap(JSValue v)
+    {
+        if (!v.isCell())
+            return 0;
+        return heap(v.asCell());
+    }
+
+    inline Heap* Heap::heap(JSCell* c)
+    {
+        return cellBlock(c)->heap;
+    }
+    
+#if ENABLE(JSC_ZOMBIES)
+    inline bool JSValue::isZombie() const
+    {
+        return isCell() && asCell() && asCell()->isZombie();
+    }
+#endif
 } // namespace JSC
 
 #endif // JSCell_h
 } // namespace JSC
 
 #endif // JSCell_h
index 7fedad7cd22a428b1aa10489372357f0b2b5474e..d213b4abdf19fad5d9922fb8446bd7d35d693507 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -45,12 +45,21 @@ ASSERT_CLASS_FITS_IN_CELL(JSFunction);
 
 const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };
 
 
 const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };
 
-JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
+bool JSFunction::isHostFunctionNonInline() const
+{
+    return isHostFunction();
+}
+
+JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure)
+    : Base(structure)
+    , m_executable(adoptRef(new VPtrHackExecutable()))
+{
+}
+
+JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
     : Base(&exec->globalData(), structure, name)
 #if ENABLE(JIT)
     : Base(&exec->globalData(), structure, name)
 #if ENABLE(JIT)
-    , m_body(FunctionBodyNode::createNativeThunk(&exec->globalData()))
-#else
-    , m_body(0)
+    , m_executable(adoptRef(new NativeExecutable(exec)))
 #endif
 {
 #if ENABLE(JIT)
 #endif
 {
 #if ENABLE(JIT)
@@ -63,32 +72,37 @@ JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int len
 #endif
 }
 
 #endif
 }
 
-JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* body, ScopeChainNode* scopeChainNode)
-    : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), name)
-    , m_body(body)
+JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode)
+    : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), executable->name())
+    , m_executable(executable)
 {
     setScopeChain(scopeChainNode);
 }
 
 JSFunction::~JSFunction()
 {
 {
     setScopeChain(scopeChainNode);
 }
 
 JSFunction::~JSFunction()
 {
+    ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
+
     // JIT code for other functions may have had calls linked directly to the code for this function; these links
     // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
     // this memory is freed and may be reused (potentially for another, different JSFunction).
     // JIT code for other functions may have had calls linked directly to the code for this function; these links
     // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
     // this memory is freed and may be reused (potentially for another, different JSFunction).
+    if (!isHostFunction()) {
 #if ENABLE(JIT_OPTIMIZE_CALL)
 #if ENABLE(JIT_OPTIMIZE_CALL)
-    if (m_body && m_body->isGenerated())
-        m_body->generatedBytecode().unlinkCallers();
+        ASSERT(m_executable);
+        if (jsExecutable()->isGenerated())
+            jsExecutable()->generatedBytecode().unlinkCallers();
 #endif
 #endif
-    if (!isHostFunction())
         scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
         scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
+    }
 }
 
 }
 
-void JSFunction::mark()
+void JSFunction::markChildren(MarkStack& markStack)
 {
 {
-    Base::mark();
-    m_body->mark();
-    if (!isHostFunction())
-        scopeChain().mark();
+    Base::markChildren(markStack);
+    if (!isHostFunction()) {
+        jsExecutable()->markAggregate(markStack);
+        scopeChain().markAggregate(markStack);
+    }
 }
 
 CallType JSFunction::getCallData(CallData& callData)
 }
 
 CallType JSFunction::getCallData(CallData& callData)
@@ -97,7 +111,7 @@ CallType JSFunction::getCallData(CallData& callData)
         callData.native.function = nativeFunction();
         return CallTypeHost;
     }
         callData.native.function = nativeFunction();
         return CallTypeHost;
     }
-    callData.js.functionBody = m_body.get();
+    callData.js.functionExecutable = jsExecutable();
     callData.js.scopeChain = scopeChain().node();
     return CallTypeJS;
 }
     callData.js.scopeChain = scopeChain().node();
     return CallTypeJS;
 }
@@ -105,7 +119,7 @@ CallType JSFunction::getCallData(CallData& callData)
 JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args)
 {
     ASSERT(!isHostFunction());
 JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args)
 {
     ASSERT(!isHostFunction());
-    return exec->interpreter()->execute(m_body.get(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot());
+    return exec->interpreter()->execute(jsExecutable(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot());
 }
 
 JSValue JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
 }
 
 JSValue JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
@@ -126,7 +140,7 @@ JSValue JSFunction::lengthGetter(ExecState* exec, const Identifier&, const Prope
 {
     JSFunction* thisObj = asFunction(slot.slotBase());
     ASSERT(!thisObj->isHostFunction());
 {
     JSFunction* thisObj = asFunction(slot.slotBase());
     ASSERT(!thisObj->isHostFunction());
-    return jsNumber(exec, thisObj->m_body->parameterCount());
+    return jsNumber(exec, thisObj->jsExecutable()->parameterCount());
 }
 
 bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 }
 
 bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -165,6 +179,46 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
     return Base::getOwnPropertySlot(exec, propertyName, slot);
 }
 
     return Base::getOwnPropertySlot(exec, propertyName, slot);
 }
 
+    bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+    {
+        if (isHostFunction())
+            return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+        
+        if (propertyName == exec->propertyNames().prototype) {
+            PropertySlot slot;
+            getOwnPropertySlot(exec, propertyName, slot);
+            return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+        }
+        
+        if (propertyName == exec->propertyNames().arguments) {
+            descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
+            return true;
+        }
+        
+        if (propertyName == exec->propertyNames().length) {
+            descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
+            return true;
+        }
+        
+        if (propertyName == exec->propertyNames().caller) {
+            descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete);
+            return true;
+        }
+        
+        return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    }
+    
+void JSFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    if (!isHostFunction() && (mode == IncludeDontEnumProperties)) {
+        propertyNames.add(exec->propertyNames().arguments);
+        propertyNames.add(exec->propertyNames().callee);
+        propertyNames.add(exec->propertyNames().caller);
+        propertyNames.add(exec->propertyNames().length);
+    }
+    Base::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
 void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     if (isHostFunction()) {
 void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     if (isHostFunction()) {
@@ -190,7 +244,7 @@ ConstructType JSFunction::getConstructData(ConstructData& constructData)
 {
     if (isHostFunction())
         return ConstructTypeNone;
 {
     if (isHostFunction())
         return ConstructTypeNone;
-    constructData.js.functionBody = m_body.get();
+    constructData.js.functionExecutable = jsExecutable();
     constructData.js.scopeChain = scopeChain().node();
     return ConstructTypeJS;
 }
     constructData.js.scopeChain = scopeChain().node();
     return ConstructTypeJS;
 }
@@ -206,7 +260,7 @@ JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
         structure = exec->lexicalGlobalObject()->emptyObjectStructure();
     JSObject* thisObj = new (exec) JSObject(structure);
 
         structure = exec->lexicalGlobalObject()->emptyObjectStructure();
     JSObject* thisObj = new (exec) JSObject(structure);
 
-    JSValue result = exec->interpreter()->execute(m_body.get(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
+    JSValue result = exec->interpreter()->execute(jsExecutable(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
     if (exec->hadException() || !result.isObject())
         return thisObj;
     return asObject(result);
     if (exec->hadException() || !result.isObject())
         return thisObj;
     return asObject(result);
index b27e5157f766fef164745420d800e907c942936b..8cd4b511371ab0f40ca145ef1f34135f5fe77f2a 100644 (file)
 #define JSFunction_h
 
 #include "InternalFunction.h"
 #define JSFunction_h
 
 #include "InternalFunction.h"
-#include "JSVariableObject.h"
-#include "SymbolTable.h"
-#include "Nodes.h"
-#include "JSObject.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class FunctionBodyNode;
+    class ExecutableBase;
+    class FunctionExecutable;
     class FunctionPrototype;
     class JSActivation;
     class JSGlobalObject;
 
     class JSFunction : public InternalFunction {
         friend class JIT;
     class FunctionPrototype;
     class JSActivation;
     class JSGlobalObject;
 
     class JSFunction : public InternalFunction {
         friend class JIT;
-        friend class VPtrSet;
+        friend class JSGlobalData;
 
         typedef InternalFunction Base;
 
 
         typedef InternalFunction Base;
 
-        JSFunction(PassRefPtr<Structure> structure)
-            : InternalFunction(structure)
-        {
-            clearScopeChain();
-        }
-
     public:
     public:
-        JSFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
-        JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*);
-        ~JSFunction();
-
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
-        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+        JSFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
+        JSFunction(ExecState*, NonNullPassRefPtr<FunctionExecutable>, ScopeChainNode*);
+        virtual ~JSFunction();
 
         JSObject* construct(ExecState*, const ArgList&);
         JSValue call(ExecState*, JSValue thisValue, const ArgList&);
 
         JSObject* construct(ExecState*, const ArgList&);
         JSValue call(ExecState*, JSValue thisValue, const ArgList&);
@@ -64,63 +51,73 @@ namespace JSC {
         void setScope(const ScopeChain& scopeChain) { setScopeChain(scopeChain); }
         ScopeChain& scope() { return scopeChain(); }
 
         void setScope(const ScopeChain& scopeChain) { setScopeChain(scopeChain); }
         ScopeChain& scope() { return scopeChain(); }
 
-        void setBody(FunctionBodyNode* body) { m_body = body; }
-        void setBody(PassRefPtr<FunctionBodyNode> body) { m_body = body; }
-        FunctionBodyNode* body() const { return m_body.get(); }
+        ExecutableBase* executable() const { return m_executable.get(); }
 
 
-        virtual void mark();
+        // To call either of these methods include Executable.h
+        inline bool isHostFunction() const;
+        FunctionExecutable* jsExecutable() const;
 
         static JS_EXPORTDATA const ClassInfo info;
 
         static PassRefPtr<Structure> createStructure(JSValue prototype) 
         { 
 
         static JS_EXPORTDATA const ClassInfo info;
 
         static PassRefPtr<Structure> createStructure(JSValue prototype) 
         { 
-            return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); 
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
         }
 
         }
 
-#if ENABLE(JIT)
-        bool isHostFunction() const { return m_body && m_body->isHostFunction(); }
-#else
-        bool isHostFunction() const { return false; }
-#endif
         NativeFunction nativeFunction()
         {
         NativeFunction nativeFunction()
         {
-            return *reinterpret_cast<NativeFunction*>(m_data);
+            return *WTF::bitwise_cast<NativeFunction*>(m_data);
         }
 
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
 
         }
 
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
 
+    protected:
+        const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | InternalFunction::StructureFlags;
+
     private:
     private:
+        JSFunction(NonNullPassRefPtr<Structure>);
+
+        bool isHostFunctionNonInline() const;
+
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+
+        virtual void markChildren(MarkStack&);
+
         virtual const ClassInfo* classInfo() const { return &info; }
 
         static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
         static JSValue callerGetter(ExecState*, const Identifier&, const PropertySlot&);
         static JSValue lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
 
         virtual const ClassInfo* classInfo() const { return &info; }
 
         static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
         static JSValue callerGetter(ExecState*, const Identifier&, const PropertySlot&);
         static JSValue lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
 
-        RefPtr<FunctionBodyNode> m_body;
+        RefPtr<ExecutableBase> m_executable;
         ScopeChain& scopeChain()
         {
         ScopeChain& scopeChain()
         {
-            ASSERT(!isHostFunction());
-            return *reinterpret_cast<ScopeChain*>(m_data);
+            ASSERT(!isHostFunctionNonInline());
+            return *WTF::bitwise_cast<ScopeChain*>(m_data);
         }
         void clearScopeChain()
         {
         }
         void clearScopeChain()
         {
-            ASSERT(!isHostFunction());
+            ASSERT(!isHostFunctionNonInline());
             new (m_data) ScopeChain(NoScopeChain());
         }
         void setScopeChain(ScopeChainNode* sc)
         {
             new (m_data) ScopeChain(NoScopeChain());
         }
         void setScopeChain(ScopeChainNode* sc)
         {
-            ASSERT(!isHostFunction());
+            ASSERT(!isHostFunctionNonInline());
             new (m_data) ScopeChain(sc);
         }
         void setScopeChain(const ScopeChain& sc)
         {
             new (m_data) ScopeChain(sc);
         }
         void setScopeChain(const ScopeChain& sc)
         {
-            ASSERT(!isHostFunction());
-            *reinterpret_cast<ScopeChain*>(m_data) = sc;
+            ASSERT(!isHostFunctionNonInline());
+            *WTF::bitwise_cast<ScopeChain*>(m_data) = sc;
         }
         void setNativeFunction(NativeFunction func)
         {
         }
         void setNativeFunction(NativeFunction func)
         {
-            *reinterpret_cast<NativeFunction*>(m_data) = func;
+            *WTF::bitwise_cast<NativeFunction*>(m_data) = func;
         }
         unsigned char m_data[sizeof(void*)];
     };
         }
         unsigned char m_data[sizeof(void*)];
     };
index 156d1023bfc20b4d8d2583005db46f6e7fb4a5d1..45abc86de1f6bd6a641815d632e306530d817594 100644 (file)
 #include "Collector.h"
 #include "CommonIdentifiers.h"
 #include "FunctionConstructor.h"
 #include "Collector.h"
 #include "CommonIdentifiers.h"
 #include "FunctionConstructor.h"
+#include "GetterSetter.h"
 #include "Interpreter.h"
 #include "JSActivation.h"
 #include "Interpreter.h"
 #include "JSActivation.h"
+#include "JSAPIValueWrapper.h"
 #include "JSArray.h"
 #include "JSByteArray.h"
 #include "JSClassRef.h"
 #include "JSFunction.h"
 #include "JSLock.h"
 #include "JSNotAnObject.h"
 #include "JSArray.h"
 #include "JSByteArray.h"
 #include "JSClassRef.h"
 #include "JSFunction.h"
 #include "JSLock.h"
 #include "JSNotAnObject.h"
+#include "JSPropertyNameIterator.h"
 #include "JSStaticScopeObject.h"
 #include "JSStaticScopeObject.h"
-#include "Parser.h"
 #include "Lexer.h"
 #include "Lookup.h"
 #include "Nodes.h"
 #include "Lexer.h"
 #include "Lookup.h"
 #include "Nodes.h"
+#include "Parser.h"
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 #include <wtf/Threading.h>
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 #include <wtf/Threading.h>
@@ -68,40 +71,38 @@ extern JSC_CONST_HASHTABLE HashTable regExpTable;
 extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
 extern JSC_CONST_HASHTABLE HashTable stringTable;
 
 extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
 extern JSC_CONST_HASHTABLE HashTable stringTable;
 
-struct VPtrSet {
-    VPtrSet();
-
-    void* jsArrayVPtr;
-    void* jsByteArrayVPtr;
-    void* jsStringVPtr;
-    void* jsFunctionVPtr;
-};
+void* JSGlobalData::jsArrayVPtr;
+void* JSGlobalData::jsByteArrayVPtr;
+void* JSGlobalData::jsStringVPtr;
+void* JSGlobalData::jsFunctionVPtr;
 
 
-VPtrSet::VPtrSet()
+void JSGlobalData::storeVPtrs()
 {
 {
-    // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
-    void* storage = fastMalloc(sizeof(CollectorBlock));
+    CollectorCell cell;
+    void* storage = &cell;
 
 
+    COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell);
     JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
     JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
-    jsArrayVPtr = jsArray->vptr();
+    JSGlobalData::jsArrayVPtr = jsArray->vptr();
     jsArray->~JSCell();
 
     jsArray->~JSCell();
 
+    COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell);
     JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
     JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
-    jsByteArrayVPtr = jsByteArray->vptr();
+    JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
     jsByteArray->~JSCell();
 
     jsByteArray->~JSCell();
 
+    COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell);
     JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
     JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
-    jsStringVPtr = jsString->vptr();
+    JSGlobalData::jsStringVPtr = jsString->vptr();
     jsString->~JSCell();
 
     jsString->~JSCell();
 
+    COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell);
     JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
     JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
-    jsFunctionVPtr = jsFunction->vptr();
+    JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
     jsFunction->~JSCell();
     jsFunction->~JSCell();
-
-    fastFree(storage);
 }
 
 }
 
-JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
+JSGlobalData::JSGlobalData(bool isShared)
     : isSharedInstance(isShared)
     , clientData(0)
     , arrayTable(fastNew<HashTable>(JSC::arrayTable))
     : isSharedInstance(isShared)
     , clientData(0)
     , arrayTable(fastNew<HashTable>(JSC::arrayTable))
@@ -118,13 +119,13 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
     , stringStructure(JSString::createStructure(jsNull()))
     , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
     , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
     , stringStructure(JSString::createStructure(jsNull()))
     , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
     , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
+    , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
+    , getterSetterStructure(GetterSetter::createStructure(jsNull()))
+    , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
+    , dummyMarkableCellStructure(JSCell::createDummyStructure())
 #if USE(JSVALUE32)
     , numberStructure(JSNumberCell::createStructure(jsNull()))
 #endif
 #if USE(JSVALUE32)
     , numberStructure(JSNumberCell::createStructure(jsNull()))
 #endif
-    , jsArrayVPtr(vptrSet.jsArrayVPtr)
-    , jsByteArrayVPtr(vptrSet.jsByteArrayVPtr)
-    , jsStringVPtr(vptrSet.jsStringVPtr)
-    , jsFunctionVPtr(vptrSet.jsFunctionVPtr)
     , identifierTable(createIdentifierTable())
     , propertyNames(new CommonIdentifiers(this))
     , emptyList(new MarkedArgumentBuffer)
     , identifierTable(createIdentifierTable())
     , propertyNames(new CommonIdentifiers(this))
     , emptyList(new MarkedArgumentBuffer)
@@ -138,8 +139,14 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
     , initializingLazyNumericCompareFunction(false)
     , head(0)
     , dynamicGlobalObject(0)
     , initializingLazyNumericCompareFunction(false)
     , head(0)
     , dynamicGlobalObject(0)
-    , scopeNodeBeingReparsed(0)
+    , functionCodeBlockBeingReparsed(0)
     , firstStringifierToMark(0)
     , firstStringifierToMark(0)
+    , markStack(jsArrayVPtr)
+    , cachedUTCOffset(NaN)
+    , weakRandom(static_cast<int>(currentTime()))
+#ifndef NDEBUG
+    , mainThreadOnly(false)
+#endif
 {
 #if PLATFORM(MAC)
     startProfilerServerIfNeeded();
 {
 #if PLATFORM(MAC)
     startProfilerServerIfNeeded();
@@ -187,9 +194,17 @@ JSGlobalData::~JSGlobalData()
     delete clientData;
 }
 
     delete clientData;
 }
 
-PassRefPtr<JSGlobalData> JSGlobalData::create(bool isShared)
+PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault()
 {
 {
-    return adoptRef(new JSGlobalData(isShared, VPtrSet()));
+    return adoptRef(new JSGlobalData(false));
+}
+
+PassRefPtr<JSGlobalData> JSGlobalData::create()
+{
+    JSGlobalData* globalData = new JSGlobalData(false);
+    setDefaultIdentifierTable(globalData->identifierTable);
+    setCurrentIdentifierTable(globalData->identifierTable);
+    return adoptRef(globalData);
 }
 
 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked()
 }
 
 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked()
@@ -209,7 +224,7 @@ JSGlobalData& JSGlobalData::sharedInstance()
 {
     JSGlobalData*& instance = sharedInstanceInternal();
     if (!instance) {
 {
     JSGlobalData*& instance = sharedInstanceInternal();
     if (!instance) {
-        instance = create(true).releaseRef();
+        instance = new JSGlobalData(true);
 #if ENABLE(JSC_MULTIPLE_THREADS)
         instance->makeUsableFromMultipleThreads();
 #endif
 #if ENABLE(JSC_MULTIPLE_THREADS)
         instance->makeUsableFromMultipleThreads();
 #endif
@@ -229,9 +244,8 @@ const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec)
 {
     if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
         initializingLazyNumericCompareFunction = true;
 {
     if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
         initializingLazyNumericCompareFunction = true;
-        RefPtr<ProgramNode> programNode = parser->parse<ProgramNode>(exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
-        RefPtr<FunctionBodyNode> functionBody = extractFunctionBody(programNode.get());
-        lazyNumericCompareFunction = functionBody->bytecode(exec->scopeChain()).instructions();
+        RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(Identifier(exec, "numericCompare"), exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
+        lazyNumericCompareFunction = function->bytecode(exec, exec->scopeChain()).instructions();
         initializingLazyNumericCompareFunction = false;
     }
 
         initializingLazyNumericCompareFunction = false;
     }
 
@@ -242,4 +256,27 @@ JSGlobalData::ClientData::~ClientData()
 {
 }
 
 {
 }
 
+void JSGlobalData::resetDateCache()
+{
+    cachedUTCOffset = NaN;
+    dstOffsetCache.reset();
+    cachedDateString = UString();
+    dateInstanceCache.reset();
+}
+
+void JSGlobalData::startSampling()
+{
+    interpreter->startSampling();
+}
+
+void JSGlobalData::stopSampling()
+{
+    interpreter->stopSampling();
+}
+
+void JSGlobalData::dumpSampleData(ExecState* exec)
+{
+    interpreter->dumpSampleData(exec);
+}
+
 } // namespace JSC
 } // namespace JSC
index 5e487f93a34610eba1fa50ab5d82f3fe934aa197..0f1f3c69ec8e34bacbf5a71d460523c732e8d3af 100644 (file)
 #define JSGlobalData_h
 
 #include "Collector.h"
 #define JSGlobalData_h
 
 #include "Collector.h"
+#include "DateInstanceCache.h"
 #include "ExecutableAllocator.h"
 #include "JITStubs.h"
 #include "JSValue.h"
 #include "ExecutableAllocator.h"
 #include "JITStubs.h"
 #include "JSValue.h"
+#include "MarkStack.h"
+#include "NumericStrings.h"
 #include "SmallStrings.h"
 #include "TimeoutChecker.h"
 #include "SmallStrings.h"
 #include "TimeoutChecker.h"
+#include "WeakRandom.h"
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
@@ -44,22 +48,40 @@ struct OpaqueJSClassContextData;
 
 namespace JSC {
 
 
 namespace JSC {
 
+    class CodeBlock;
     class CommonIdentifiers;
     class CommonIdentifiers;
-    class FunctionBodyNode;
     class IdentifierTable;
     class IdentifierTable;
-    class Instruction;
     class Interpreter;
     class JSGlobalObject;
     class JSObject;
     class Lexer;
     class Parser;
     class Interpreter;
     class JSGlobalObject;
     class JSObject;
     class Lexer;
     class Parser;
-    class ScopeNode;
     class Stringifier;
     class Structure;
     class UString;
 
     struct HashTable;
     class Stringifier;
     class Structure;
     class UString;
 
     struct HashTable;
-    struct VPtrSet;
+    struct Instruction;    
+
+    struct DSTOffsetCache {
+        DSTOffsetCache()
+        {
+            reset();
+        }
+        
+        void reset()
+        {
+            offset = 0.0;
+            start = 0.0;
+            end = -1.0;
+            increment = 0.0;
+        }
+
+        double offset;
+        double start;
+        double end;
+        double increment;
+    };
 
     class JSGlobalData : public RefCounted<JSGlobalData> {
     public:
 
     class JSGlobalData : public RefCounted<JSGlobalData> {
     public:
@@ -70,8 +92,9 @@ namespace JSC {
         static bool sharedInstanceExists();
         static JSGlobalData& sharedInstance();
 
         static bool sharedInstanceExists();
         static JSGlobalData& sharedInstance();
 
-        static PassRefPtr<JSGlobalData> create(bool isShared = false);
+        static PassRefPtr<JSGlobalData> create();
         static PassRefPtr<JSGlobalData> createLeaked();
         static PassRefPtr<JSGlobalData> createLeaked();
+        static PassRefPtr<JSGlobalData> createNonDefault();
         ~JSGlobalData();
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
         ~JSGlobalData();
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
@@ -97,20 +120,28 @@ namespace JSC {
         RefPtr<Structure> stringStructure;
         RefPtr<Structure> notAnObjectErrorStubStructure;
         RefPtr<Structure> notAnObjectStructure;
         RefPtr<Structure> stringStructure;
         RefPtr<Structure> notAnObjectErrorStubStructure;
         RefPtr<Structure> notAnObjectStructure;
+        RefPtr<Structure> propertyNameIteratorStructure;
+        RefPtr<Structure> getterSetterStructure;
+        RefPtr<Structure> apiWrapperStructure;
+        RefPtr<Structure> dummyMarkableCellStructure;
+
 #if USE(JSVALUE32)
         RefPtr<Structure> numberStructure;
 #endif
 
 #if USE(JSVALUE32)
         RefPtr<Structure> numberStructure;
 #endif
 
-        void* jsArrayVPtr;
-        void* jsByteArrayVPtr;
-        void* jsStringVPtr;
-        void* jsFunctionVPtr;
+        static void storeVPtrs();
+        static JS_EXPORTDATA void* jsArrayVPtr;
+        static JS_EXPORTDATA void* jsByteArrayVPtr;
+        static JS_EXPORTDATA void* jsStringVPtr;
+        static JS_EXPORTDATA void* jsFunctionVPtr;
 
         IdentifierTable* identifierTable;
         CommonIdentifiers* propertyNames;
         const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
         SmallStrings smallStrings;
 
         IdentifierTable* identifierTable;
         CommonIdentifiers* propertyNames;
         const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
         SmallStrings smallStrings;
-
+        NumericStrings numericStrings;
+        DateInstanceCache dateInstanceCache;
+        
 #if ENABLE(ASSEMBLER)
         ExecutableAllocator executableAllocator;
 #endif
 #if ENABLE(ASSEMBLER)
         ExecutableAllocator executableAllocator;
 #endif
@@ -140,15 +171,34 @@ namespace JSC {
 
         HashSet<JSObject*> arrayVisitedElements;
 
 
         HashSet<JSObject*> arrayVisitedElements;
 
-        ScopeNode* scopeNodeBeingReparsed;
+        CodeBlock* functionCodeBlockBeingReparsed;
         Stringifier* firstStringifierToMark;
 
         Stringifier* firstStringifierToMark;
 
+        MarkStack markStack;
+
+        double cachedUTCOffset;
+        DSTOffsetCache dstOffsetCache;
+        
+        UString cachedDateString;
+        double cachedDateStringValue;
+        
+        WeakRandom weakRandom;
+
+#ifndef NDEBUG
+        bool mainThreadOnly;
+#endif
+
+        void resetDateCache();
+
+        void startSampling();
+        void stopSampling();
+        void dumpSampleData(ExecState* exec);
     private:
     private:
-        JSGlobalData(bool isShared, const VPtrSet&);
+        JSGlobalData(bool isShared);
         static JSGlobalData*& sharedInstanceInternal();
         void createNativeThunk();
     };
         static JSGlobalData*& sharedInstanceInternal();
         void createNativeThunk();
     };
-
+    
 } // namespace JSC
 
 #endif // JSGlobalData_h
 } // namespace JSC
 
 #endif // JSGlobalData_h
index c56b84b0e7a46b5b46aff060ce3258daa3cc8d34..4bf0a6904c32d8a9ee4eb3d058f5d4e205330a4a 100644 (file)
@@ -80,16 +80,16 @@ static const int initialTickCountThreshold = 255;
 // Preferred number of milliseconds between each timeout check
 static const int preferredScriptCheckTimeInterval = 1000;
 
 // Preferred number of milliseconds between each timeout check
 static const int preferredScriptCheckTimeInterval = 1000;
 
-static inline void markIfNeeded(JSValue v)
+static inline void markIfNeeded(MarkStack& markStack, JSValue v)
 {
 {
-    if (v && !v.marked())
-        v.mark();
+    if (v)
+        markStack.append(v);
 }
 
 }
 
-static inline void markIfNeeded(const RefPtr<Structure>& s)
+static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s)
 {
     if (s)
 {
     if (s)
-        s->mark();
+        markIfNeeded(markStack, s->storedPrototype());
 }
 
 JSGlobalObject::~JSGlobalObject()
 }
 
 JSGlobalObject::~JSGlobalObject()
@@ -112,8 +112,8 @@ JSGlobalObject::~JSGlobalObject()
     if (headObject == this)
         headObject = 0;
 
     if (headObject == this)
         headObject = 0;
 
-    HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
-    for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+    HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end();
+    for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
         (*it)->clearGlobalObject();
         
     RegisterFile& registerFile = globalData()->interpreter->registerFile();
         (*it)->clearGlobalObject();
         
     RegisterFile& registerFile = globalData()->interpreter->registerFile();
@@ -121,15 +121,17 @@ JSGlobalObject::~JSGlobalObject()
         registerFile.setGlobalObject(0);
         registerFile.setNumGlobals(0);
     }
         registerFile.setGlobalObject(0);
         registerFile.setNumGlobals(0);
     }
-    delete d();
+    d()->destructor(d());
 }
 
 void JSGlobalObject::init(JSObject* thisValue)
 {
     ASSERT(JSLock::currentThreadIsHoldingLock());
 
 }
 
 void JSGlobalObject::init(JSObject* thisValue)
 {
     ASSERT(JSLock::currentThreadIsHoldingLock());
 
+    structure()->disableSpecificFunctionTracking();
+
     d()->globalData = Heap::heap(this)->globalData();
     d()->globalData = Heap::heap(this)->globalData();
-    d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), thisValue);
+    d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), this, thisValue);
 
     JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.node(), CallFrame::noCaller(), 0, 0, 0);
 
 
     JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.node(), CallFrame::noCaller(), 0, 0, 0);
 
@@ -175,18 +177,18 @@ void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& proper
     }
 }
 
     }
 }
 
-void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc)
+void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes)
 {
     PropertySlot slot;
     if (!symbolTableGet(propertyName, slot))
 {
     PropertySlot slot;
     if (!symbolTableGet(propertyName, slot))
-        JSVariableObject::defineGetter(exec, propertyName, getterFunc);
+        JSVariableObject::defineGetter(exec, propertyName, getterFunc, attributes);
 }
 
 }
 
-void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc)
+void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes)
 {
     PropertySlot slot;
     if (!symbolTableGet(propertyName, slot))
 {
     PropertySlot slot;
     if (!symbolTableGet(propertyName, slot))
-        JSVariableObject::defineSetter(exec, propertyName, setterFunc);
+        JSVariableObject::defineSetter(exec, propertyName, setterFunc, attributes);
 }
 
 static inline JSObject* lastInPrototypeChain(JSObject* object)
 }
 
 static inline JSObject* lastInPrototypeChain(JSObject* object)
@@ -256,9 +258,9 @@ void JSGlobalObject::reset(JSValue prototype)
 
     // Constructors
 
 
     // Constructors
 
-    JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype);
+    JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype, d()->prototypeFunctionStructure.get());
     JSCell* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype);
     JSCell* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype);
-    JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype);
+    JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype, d()->prototypeFunctionStructure.get());
     JSCell* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
     JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype);
     JSCell* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype);
     JSCell* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
     JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype);
     JSCell* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype);
@@ -357,43 +359,58 @@ void JSGlobalObject::resetPrototype(JSValue prototype)
         oldLastInPrototypeChain->setPrototype(objectPrototype);
 }
 
         oldLastInPrototypeChain->setPrototype(objectPrototype);
 }
 
-void JSGlobalObject::mark()
+void JSGlobalObject::markChildren(MarkStack& markStack)
 {
 {
-    JSVariableObject::mark();
+    JSVariableObject::markChildren(markStack);
     
     
-    HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
-    for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
-        (*it)->mark();
+    HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end();
+    for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+        (*it)->markAggregate(markStack);
 
     RegisterFile& registerFile = globalData()->interpreter->registerFile();
     if (registerFile.globalObject() == this)
 
     RegisterFile& registerFile = globalData()->interpreter->registerFile();
     if (registerFile.globalObject() == this)
-        registerFile.markGlobals(&globalData()->heap);
-
-    markIfNeeded(d()->regExpConstructor);
-    markIfNeeded(d()->errorConstructor);
-    markIfNeeded(d()->evalErrorConstructor);
-    markIfNeeded(d()->rangeErrorConstructor);
-    markIfNeeded(d()->referenceErrorConstructor);
-    markIfNeeded(d()->syntaxErrorConstructor);
-    markIfNeeded(d()->typeErrorConstructor);
-    markIfNeeded(d()->URIErrorConstructor);
-
-    markIfNeeded(d()->evalFunction);
-    markIfNeeded(d()->callFunction);
-    markIfNeeded(d()->applyFunction);
-
-    markIfNeeded(d()->objectPrototype);
-    markIfNeeded(d()->functionPrototype);
-    markIfNeeded(d()->arrayPrototype);
-    markIfNeeded(d()->booleanPrototype);
-    markIfNeeded(d()->stringPrototype);
-    markIfNeeded(d()->numberPrototype);
-    markIfNeeded(d()->datePrototype);
-    markIfNeeded(d()->regExpPrototype);
-
-    markIfNeeded(d()->methodCallDummy);
-
-    markIfNeeded(d()->errorStructure);
+        registerFile.markGlobals(markStack, &globalData()->heap);
+
+    markIfNeeded(markStack, d()->regExpConstructor);
+    markIfNeeded(markStack, d()->errorConstructor);
+    markIfNeeded(markStack, d()->evalErrorConstructor);
+    markIfNeeded(markStack, d()->rangeErrorConstructor);
+    markIfNeeded(markStack, d()->referenceErrorConstructor);
+    markIfNeeded(markStack, d()->syntaxErrorConstructor);
+    markIfNeeded(markStack, d()->typeErrorConstructor);
+    markIfNeeded(markStack, d()->URIErrorConstructor);
+
+    markIfNeeded(markStack, d()->evalFunction);
+    markIfNeeded(markStack, d()->callFunction);
+    markIfNeeded(markStack, d()->applyFunction);
+
+    markIfNeeded(markStack, d()->objectPrototype);
+    markIfNeeded(markStack, d()->functionPrototype);
+    markIfNeeded(markStack, d()->arrayPrototype);
+    markIfNeeded(markStack, d()->booleanPrototype);
+    markIfNeeded(markStack, d()->stringPrototype);
+    markIfNeeded(markStack, d()->numberPrototype);
+    markIfNeeded(markStack, d()->datePrototype);
+    markIfNeeded(markStack, d()->regExpPrototype);
+
+    markIfNeeded(markStack, d()->methodCallDummy);
+
+    markIfNeeded(markStack, d()->errorStructure);
+    markIfNeeded(markStack, d()->argumentsStructure);
+    markIfNeeded(markStack, d()->arrayStructure);
+    markIfNeeded(markStack, d()->booleanObjectStructure);
+    markIfNeeded(markStack, d()->callbackConstructorStructure);
+    markIfNeeded(markStack, d()->callbackFunctionStructure);
+    markIfNeeded(markStack, d()->callbackObjectStructure);
+    markIfNeeded(markStack, d()->dateStructure);
+    markIfNeeded(markStack, d()->emptyObjectStructure);
+    markIfNeeded(markStack, d()->errorStructure);
+    markIfNeeded(markStack, d()->functionStructure);
+    markIfNeeded(markStack, d()->numberObjectStructure);
+    markIfNeeded(markStack, d()->prototypeFunctionStructure);
+    markIfNeeded(markStack, d()->regExpMatchesArrayStructure);
+    markIfNeeded(markStack, d()->regExpStructure);
+    markIfNeeded(markStack, d()->stringObjectStructure);
 
     // No need to mark the other structures, because their prototypes are all
     // guaranteed to be referenced elsewhere.
 
     // No need to mark the other structures, because their prototypes are all
     // guaranteed to be referenced elsewhere.
@@ -403,11 +420,7 @@ void JSGlobalObject::mark()
         return;
 
     size_t size = d()->registerArraySize;
         return;
 
     size_t size = d()->registerArraySize;
-    for (size_t i = 0; i < size; ++i) {
-        Register& r = registerArray[i];
-        if (!r.marked())
-            r.mark();
-    }
+    markStack.appendValues(reinterpret_cast<JSValue*>(registerArray), size);
 }
 
 ExecState* JSGlobalObject::globalExec()
 }
 
 ExecState* JSGlobalObject::globalExec()
@@ -452,11 +465,12 @@ void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
 
 void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
 {
 
 void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
 {
-#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
-    return globalData->heap.inlineAllocate(size);
-#else
     return globalData->heap.allocate(size);
     return globalData->heap.allocate(size);
-#endif
+}
+
+void JSGlobalObject::destroyJSGlobalObjectData(void* jsGlobalObjectData)
+{
+    delete static_cast<JSGlobalObjectData*>(jsGlobalObjectData);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index bad3a45a9f9f5e59a79b96c25e5b5b93aac1ee4f..bb0836256ea57065836ba114c8823b49c0a6ae01 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
 /*
  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *  Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -22,6 +22,7 @@
 #ifndef JSGlobalObject_h
 #define JSGlobalObject_h
 
 #ifndef JSGlobalObject_h
 #define JSGlobalObject_h
 
+#include "JSArray.h"
 #include "JSGlobalData.h"
 #include "JSVariableObject.h"
 #include "NativeFunctionWrapper.h"
 #include "JSGlobalData.h"
 #include "JSVariableObject.h"
 #include "NativeFunctionWrapper.h"
@@ -38,6 +39,7 @@ namespace JSC {
     class Debugger;
     class ErrorConstructor;
     class FunctionPrototype;
     class Debugger;
     class ErrorConstructor;
     class FunctionPrototype;
+    class GlobalCodeBlock;
     class GlobalEvalFunction;
     class NativeErrorConstructor;
     class ProgramCodeBlock;
     class GlobalEvalFunction;
     class NativeErrorConstructor;
     class ProgramCodeBlock;
@@ -50,14 +52,22 @@ namespace JSC {
     struct HashTable;
 
     typedef Vector<ExecState*, 16> ExecStateStack;
     struct HashTable;
 
     typedef Vector<ExecState*, 16> ExecStateStack;
-
+    
     class JSGlobalObject : public JSVariableObject {
     protected:
         using JSVariableObject::JSVariableObjectData;
 
         struct JSGlobalObjectData : public JSVariableObjectData {
     class JSGlobalObject : public JSVariableObject {
     protected:
         using JSVariableObject::JSVariableObjectData;
 
         struct JSGlobalObjectData : public JSVariableObjectData {
-            JSGlobalObjectData()
+            // We use an explicit destructor function pointer instead of a
+            // virtual destructor because we want to avoid adding a vtable
+            // pointer to this struct. Adding a vtable pointer would force the
+            // compiler to emit costly pointer fixup code when casting from
+            // JSVariableObjectData* to JSGlobalObjectData*.
+            typedef void (*Destructor)(void*);
+
+            JSGlobalObjectData(Destructor destructor)
                 : JSVariableObjectData(&symbolTable, 0)
                 : JSVariableObjectData(&symbolTable, 0)
+                , destructor(destructor)
                 , registerArraySize(0)
                 , globalScopeChain(NoScopeChain())
                 , regExpConstructor(0)
                 , registerArraySize(0)
                 , globalScopeChain(NoScopeChain())
                 , regExpConstructor(0)
@@ -83,10 +93,8 @@ namespace JSC {
             {
             }
             
             {
             }
             
-            virtual ~JSGlobalObjectData()
-            {
-            }
-
+            Destructor destructor;
+            
             size_t registerArraySize;
 
             JSGlobalObject* next;
             size_t registerArraySize;
 
             JSGlobalObject* next;
@@ -144,20 +152,20 @@ namespace JSC {
 
             RefPtr<JSGlobalData> globalData;
 
 
             RefPtr<JSGlobalData> globalData;
 
-            HashSet<ProgramCodeBlock*> codeBlocks;
+            HashSet<GlobalCodeBlock*> codeBlocks;
         };
 
     public:
         void* operator new(size_t, JSGlobalData*);
 
         explicit JSGlobalObject()
         };
 
     public:
         void* operator new(size_t, JSGlobalData*);
 
         explicit JSGlobalObject()
-            : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData)
+            : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData(destroyJSGlobalObjectData))
         {
             init(this);
         }
 
     protected:
         {
             init(this);
         }
 
     protected:
-        JSGlobalObject(PassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue)
+        JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue)
             : JSVariableObject(structure, data)
         {
             init(thisValue);
             : JSVariableObject(structure, data)
         {
             init(thisValue);
@@ -166,15 +174,16 @@ namespace JSC {
     public:
         virtual ~JSGlobalObject();
 
     public:
         virtual ~JSGlobalObject();
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
         virtual bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
         virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
         virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
 
         virtual bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
         virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
         virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
 
-        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc);
-        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc);
+        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
+        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
 
         // Linked list of all global objects that use the same JSGlobalData.
         JSGlobalObject*& head() { return d()->globalData->head; }
 
         // Linked list of all global objects that use the same JSGlobalData.
         JSGlobalObject*& head() { return d()->globalData->head; }
@@ -247,7 +256,7 @@ namespace JSC {
 
         virtual bool isDynamicScope() const;
 
 
         virtual bool isDynamicScope() const;
 
-        HashSet<ProgramCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
+        HashSet<GlobalCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
 
         void copyGlobalsFrom(RegisterFile&);
         void copyGlobalsTo(RegisterFile&);
 
         void copyGlobalsFrom(RegisterFile&);
         void copyGlobalsTo(RegisterFile&);
@@ -259,10 +268,13 @@ namespace JSC {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType));
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
 
     protected:
         }
 
     protected:
+
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
+
         struct GlobalPropertyInfo {
             GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
                 : identifier(i)
         struct GlobalPropertyInfo {
             GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
                 : identifier(i)
@@ -278,6 +290,8 @@ namespace JSC {
         void addStaticGlobals(GlobalPropertyInfo*, int count);
 
     private:
         void addStaticGlobals(GlobalPropertyInfo*, int count);
 
     private:
+        static void destroyJSGlobalObjectData(void*);
+
         // FIXME: Fold reset into init.
         void init(JSObject* thisValue);
         void reset(JSValue prototype);
         // FIXME: Fold reset into init.
         void init(JSObject* thisValue);
         void reset(JSValue prototype);
@@ -326,6 +340,13 @@ namespace JSC {
         return symbolTableGet(propertyName, slot);
     }
 
         return symbolTableGet(propertyName, slot);
     }
 
+    inline bool JSGlobalObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+    {
+        if (symbolTableGet(propertyName, descriptor))
+            return true;
+        return JSVariableObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    }
+
     inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
     {
         PropertySlot slot;
     inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
     {
         PropertySlot slot;
@@ -335,14 +356,6 @@ namespace JSC {
         return symbolTableGet(propertyName, slot, slotIsWriteable);
     }
 
         return symbolTableGet(propertyName, slot, slotIsWriteable);
     }
 
-    inline JSGlobalObject* ScopeChainNode::globalObject() const
-    {
-        const ScopeChainNode* n = this;
-        while (n->next)
-            n = n->next;
-        return asGlobalObject(n->object);
-    }
-
     inline JSValue Structure::prototypeForLookup(ExecState* exec) const
     {
         if (typeInfo().type() == ObjectType)
     inline JSValue Structure::prototypeForLookup(ExecState* exec) const
     {
         if (typeInfo().type() == ObjectType)
@@ -397,13 +410,56 @@ namespace JSC {
         return globalData().dynamicGlobalObject;
     }
 
         return globalData().dynamicGlobalObject;
     }
 
-    class DynamicGlobalObjectScope : Noncopyable {
+    inline JSObject* constructEmptyObject(ExecState* exec)
+    {
+        return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+    }
+    
+    inline JSObject* constructEmptyObject(ExecState* exec, JSGlobalObject* globalObject)
+    {
+        return new (exec) JSObject(globalObject->emptyObjectStructure());
+    }
+
+    inline JSArray* constructEmptyArray(ExecState* exec)
+    {
+        return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());
+    }
+    
+    inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject)
+    {
+        return new (exec) JSArray(globalObject->arrayStructure());
+    }
+
+    inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
+    {
+        return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength);
+    }
+
+    inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
+    {
+        MarkedArgumentBuffer values;
+        values.append(singleItemValue);
+        return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
+    }
+
+    inline JSArray* constructArray(ExecState* exec, const ArgList& values)
+    {
+        return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
+    }
+
+    class DynamicGlobalObjectScope : public Noncopyable {
     public:
         DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject) 
             : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
             , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
         {
     public:
         DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject) 
             : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
             , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
         {
-            m_dynamicGlobalObjectSlot = dynamicGlobalObject;
+            if (!m_dynamicGlobalObjectSlot) {
+                m_dynamicGlobalObjectSlot = dynamicGlobalObject;
+
+                // Reset the date cache between JS invocations to force the VM
+                // to observe time zone changes.
+                callFrame->globalData().resetDateCache();
+            }
         }
 
         ~DynamicGlobalObjectScope()
         }
 
         ~DynamicGlobalObjectScope()
index be160a823c391f400ca1cc01f88f41a773f25bb6..2ddc41c030533b739575e700ff84b3de3afd2198 100644 (file)
 
 #include "CallFrame.h"
 #include "GlobalEvalFunction.h"
 
 #include "CallFrame.h"
 #include "GlobalEvalFunction.h"
+#include "Interpreter.h"
 #include "JSGlobalObject.h"
 #include "JSGlobalObject.h"
-#include "LiteralParser.h"
 #include "JSString.h"
 #include "JSString.h"
-#include "Interpreter.h"
-#include "Parser.h"
-#include "dtoa.h"
 #include "Lexer.h"
 #include "Lexer.h"
+#include "LiteralParser.h"
 #include "Nodes.h"
 #include "Nodes.h"
+#include "Parser.h"
+#include "StringBuilder.h"
+#include "StringExtras.h"
+#include "dtoa.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -55,24 +57,24 @@ static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEsc
     if (!cstr.c_str())
         return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");
 
     if (!cstr.c_str())
         return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");
 
-    UString result = "";
+    StringBuilder builder;
     const char* p = cstr.c_str();
     for (size_t k = 0; k < cstr.size(); k++, p++) {
         char c = *p;
         if (c && strchr(doNotEscape, c))
     const char* p = cstr.c_str();
     for (size_t k = 0; k < cstr.size(); k++, p++) {
         char c = *p;
         if (c && strchr(doNotEscape, c))
-            result.append(c);
+            builder.append(c);
         else {
             char tmp[4];
             snprintf(tmp, sizeof(tmp), "%%%02X", static_cast<unsigned char>(c));
         else {
             char tmp[4];
             snprintf(tmp, sizeof(tmp), "%%%02X", static_cast<unsigned char>(c));
-            result += tmp;
+            builder.append((const char*)tmp);
         }
     }
         }
     }
-    return jsString(exec, result);
+    return jsString(exec, builder.release());
 }
 
 static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict)
 {
 }
 
 static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict)
 {
-    UString result = "";
+    StringBuilder builder;
     UString str = args.at(0).toString(exec);
     int k = 0;
     int len = str.size();
     UString str = args.at(0).toString(exec);
     int k = 0;
     int len = str.size();
@@ -106,7 +108,7 @@ static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUne
                             charLen = 0;
                         else if (character >= 0x10000) {
                             // Convert to surrogate pair.
                             charLen = 0;
                         else if (character >= 0x10000) {
                             // Convert to surrogate pair.
-                            result.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));
+                            builder.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));
                             u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));
                         } else
                             u = static_cast<UChar>(character);
                             u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));
                         } else
                             u = static_cast<UChar>(character);
@@ -131,9 +133,9 @@ static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUne
             }
         }
         k++;
             }
         }
         k++;
-        result.append(c);
+        builder.append(c);
     }
     }
-    return jsString(exec, result);
+    return jsString(exec, builder.release());
 }
 
 bool isStrWhiteSpace(UChar c)
 }
 
 bool isStrWhiteSpace(UChar c)
@@ -286,16 +288,12 @@ JSValue JSC_HOST_CALL globalFuncEval(ExecState* exec, JSObject* function, JSValu
     if (JSValue parsedObject = preparser.tryLiteralParse())
         return parsedObject;
 
     if (JSValue parsedObject = preparser.tryLiteralParse())
         return parsedObject;
 
-    int errLine;
-    UString errMsg;
-
-    SourceCode source = makeSource(s);
-    RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-
-    if (!evalNode)
-        return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), NULL);
+    RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s));
+    JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node());
+    if (error)
+        return throwError(exec, error);
 
 
-    return exec->interpreter()->execute(evalNode.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot());
+    return exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot());
 }
 
 JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 }
 
 JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
@@ -380,7 +378,7 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons
         "0123456789"
         "*+-./@_";
 
         "0123456789"
         "*+-./@_";
 
-    UString result = "";
+    StringBuilder builder;
     UString s;
     UString str = args.at(0).toString(exec);
     const UChar* c = str.data();
     UString s;
     UString str = args.at(0).toString(exec);
     const UChar* c = str.data();
@@ -397,15 +395,15 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons
             snprintf(tmp, sizeof(tmp), "%%%02X", u);
             s = UString(tmp);
         }
             snprintf(tmp, sizeof(tmp), "%%%02X", u);
             s = UString(tmp);
         }
-        result += s;
+        builder.append(s);
     }
 
     }
 
-    return jsString(exec, result);
+    return jsString(exec, builder.release());
 }
 
 JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    UString result = "";
+    StringBuilder builder;
     UString str = args.at(0).toString(exec);
     int k = 0;
     int len = str.size();
     UString str = args.at(0).toString(exec);
     int k = 0;
     int len = str.size();
@@ -424,10 +422,10 @@ JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, co
             k += 2;
         }
         k++;
             k += 2;
         }
         k++;
-        result.append(*c);
+        builder.append(*c);
     }
 
     }
 
-    return jsString(exec, result);
+    return jsString(exec, builder.release());
 }
 
 #ifndef NDEBUG
 }
 
 #ifndef NDEBUG
index 7ece5da3d6b918fc8824369fa1684980d89ddaf1..8f056c81748ee562b21913969152bc7894b4c0b3 100644 (file)
@@ -60,23 +60,23 @@ static void setLockCount(intptr_t count)
 }
 
 JSLock::JSLock(ExecState* exec)
 }
 
 JSLock::JSLock(ExecState* exec)
-    : m_lockingForReal(exec->globalData().isSharedInstance)
+    : m_lockBehavior(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly)
 {
 {
-    lock(m_lockingForReal);
+    lock(m_lockBehavior);
 }
 
 }
 
-void JSLock::lock(bool lockForReal)
+void JSLock::lock(JSLockBehavior lockBehavior)
 {
 #ifdef NDEBUG
     // Locking "not for real" is a debug-only feature.
 {
 #ifdef NDEBUG
     // Locking "not for real" is a debug-only feature.
-    if (!lockForReal)
+    if (lockBehavior == SilenceAssertionsOnly)
         return;
 #endif
 
     pthread_once(&createJSLockCountOnce, createJSLockCount);
 
     intptr_t currentLockCount = lockCount();
         return;
 #endif
 
     pthread_once(&createJSLockCountOnce, createJSLockCount);
 
     intptr_t currentLockCount = lockCount();
-    if (!currentLockCount && lockForReal) {
+    if (!currentLockCount && lockBehavior == LockForReal) {
         int result;
         result = pthread_mutex_lock(&JSMutex);
         ASSERT(!result);
         int result;
         result = pthread_mutex_lock(&JSMutex);
         ASSERT(!result);
@@ -84,19 +84,19 @@ void JSLock::lock(bool lockForReal)
     setLockCount(currentLockCount + 1);
 }
 
     setLockCount(currentLockCount + 1);
 }
 
-void JSLock::unlock(bool lockForReal)
+void JSLock::unlock(JSLockBehavior lockBehavior)
 {
     ASSERT(lockCount());
 
 #ifdef NDEBUG
     // Locking "not for real" is a debug-only feature.
 {
     ASSERT(lockCount());
 
 #ifdef NDEBUG
     // Locking "not for real" is a debug-only feature.
-    if (!lockForReal)
+    if (lockBehavior == SilenceAssertionsOnly)
         return;
 #endif
 
     intptr_t newLockCount = lockCount() - 1;
     setLockCount(newLockCount);
         return;
 #endif
 
     intptr_t newLockCount = lockCount() - 1;
     setLockCount(newLockCount);
-    if (!newLockCount && lockForReal) {
+    if (!newLockCount && lockBehavior == LockForReal) {
         int result;
         result = pthread_mutex_unlock(&JSMutex);
         ASSERT(!result);
         int result;
         result = pthread_mutex_unlock(&JSMutex);
         ASSERT(!result);
@@ -105,12 +105,12 @@ void JSLock::unlock(bool lockForReal)
 
 void JSLock::lock(ExecState* exec)
 {
 
 void JSLock::lock(ExecState* exec)
 {
-    lock(exec->globalData().isSharedInstance);
+    lock(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly);
 }
 
 void JSLock::unlock(ExecState* exec)
 {
 }
 
 void JSLock::unlock(ExecState* exec)
 {
-    unlock(exec->globalData().isSharedInstance);
+    unlock(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly);
 }
 
 bool JSLock::currentThreadIsHoldingLock()
 }
 
 bool JSLock::currentThreadIsHoldingLock()
@@ -162,7 +162,7 @@ bool JSLock::currentThreadIsHoldingLock()
 static unsigned lockDropDepth = 0;
 
 JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
 static unsigned lockDropDepth = 0;
 
 JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
-    : m_lockingForReal(exec->globalData().isSharedInstance)
+    : m_lockBehavior(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly)
 {
     pthread_once(&createJSLockCountOnce, createJSLockCount);
 
 {
     pthread_once(&createJSLockCountOnce, createJSLockCount);
 
@@ -173,11 +173,11 @@ JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
 
     m_lockCount = JSLock::lockCount();
     for (intptr_t i = 0; i < m_lockCount; i++)
 
     m_lockCount = JSLock::lockCount();
     for (intptr_t i = 0; i < m_lockCount; i++)
-        JSLock::unlock(m_lockingForReal);
+        JSLock::unlock(m_lockBehavior);
 }
 
 }
 
-JSLock::DropAllLocks::DropAllLocks(bool lockingForReal)
-    : m_lockingForReal(lockingForReal)
+JSLock::DropAllLocks::DropAllLocks(JSLockBehavior JSLockBehavior)
+    : m_lockBehavior(JSLockBehavior)
 {
     pthread_once(&createJSLockCountOnce, createJSLockCount);
 
 {
     pthread_once(&createJSLockCountOnce, createJSLockCount);
 
@@ -191,13 +191,13 @@ JSLock::DropAllLocks::DropAllLocks(bool lockingForReal)
 
     m_lockCount = JSLock::lockCount();
     for (intptr_t i = 0; i < m_lockCount; i++)
 
     m_lockCount = JSLock::lockCount();
     for (intptr_t i = 0; i < m_lockCount; i++)
-        JSLock::unlock(m_lockingForReal);
+        JSLock::unlock(m_lockBehavior);
 }
 
 JSLock::DropAllLocks::~DropAllLocks()
 {
     for (intptr_t i = 0; i < m_lockCount; i++)
 }
 
 JSLock::DropAllLocks::~DropAllLocks()
 {
     for (intptr_t i = 0; i < m_lockCount; i++)
-        JSLock::lock(m_lockingForReal);
+        JSLock::lock(m_lockBehavior);
 
     --lockDropDepth;
 }
 
     --lockDropDepth;
 }
@@ -205,7 +205,7 @@ JSLock::DropAllLocks::~DropAllLocks()
 #else
 
 JSLock::JSLock(ExecState*)
 #else
 
 JSLock::JSLock(ExecState*)
-    : m_lockingForReal(false)
+    : m_lockBehavior(SilenceAssertionsOnly)
 {
 }
 
 {
 }
 
@@ -221,11 +221,11 @@ bool JSLock::currentThreadIsHoldingLock()
     return true;
 }
 
     return true;
 }
 
-void JSLock::lock(bool)
+void JSLock::lock(JSLockBehavior)
 {
 }
 
 {
 }
 
-void JSLock::unlock(bool)
+void JSLock::unlock(JSLockBehavior)
 {
 }
 
 {
 }
 
@@ -241,7 +241,7 @@ JSLock::DropAllLocks::DropAllLocks(ExecState*)
 {
 }
 
 {
 }
 
-JSLock::DropAllLocks::DropAllLocks(bool)
+JSLock::DropAllLocks::DropAllLocks(JSLockBehavior)
 {
 }
 
 {
 }
 
index 3dde358942d1630f8c12fb30083e5d18b59eb4ac..8b015c4c88d44c9ee56c49658558138e23400d33 100644 (file)
@@ -50,50 +50,52 @@ namespace JSC {
 
     class ExecState;
 
 
     class ExecState;
 
-    class JSLock : Noncopyable {
+    enum JSLockBehavior { SilenceAssertionsOnly, LockForReal };
+
+    class JSLock : public Noncopyable {
     public:
         JSLock(ExecState*);
 
     public:
         JSLock(ExecState*);
 
-        JSLock(bool lockingForReal)
-            : m_lockingForReal(lockingForReal)
+        JSLock(JSLockBehavior lockBehavior)
+            : m_lockBehavior(lockBehavior)
         {
 #ifdef NDEBUG
             // Locking "not for real" is a debug-only feature.
         {
 #ifdef NDEBUG
             // Locking "not for real" is a debug-only feature.
-            if (!lockingForReal)
+            if (lockBehavior == SilenceAssertionsOnly)
                 return;
 #endif
                 return;
 #endif
-            lock(lockingForReal);
+            lock(lockBehavior);
         }
 
         ~JSLock()
         { 
 #ifdef NDEBUG
             // Locking "not for real" is a debug-only feature.
         }
 
         ~JSLock()
         { 
 #ifdef NDEBUG
             // Locking "not for real" is a debug-only feature.
-            if (!m_lockingForReal)
+            if (m_lockBehavior == SilenceAssertionsOnly)
                 return;
 #endif
                 return;
 #endif
-            unlock(m_lockingForReal); 
+            unlock(m_lockBehavior); 
         }
         
         }
         
-        static void lock(bool);
-        static void unlock(bool);
+        static void lock(JSLockBehavior);
+        static void unlock(JSLockBehavior);
         static void lock(ExecState*);
         static void unlock(ExecState*);
 
         static intptr_t lockCount();
         static bool currentThreadIsHoldingLock();
 
         static void lock(ExecState*);
         static void unlock(ExecState*);
 
         static intptr_t lockCount();
         static bool currentThreadIsHoldingLock();
 
-        bool m_lockingForReal;
+        JSLockBehavior m_lockBehavior;
 
 
-        class DropAllLocks : Noncopyable {
+        class DropAllLocks : public Noncopyable {
         public:
             DropAllLocks(ExecState* exec);
         public:
             DropAllLocks(ExecState* exec);
-            DropAllLocks(bool);
+            DropAllLocks(JSLockBehavior);
             ~DropAllLocks();
             
         private:
             intptr_t m_lockCount;
             ~DropAllLocks();
             
         private:
             intptr_t m_lockCount;
-            bool m_lockingForReal;
+            JSLockBehavior m_lockBehavior;
         };
     };
 
         };
     };
 
index 937dc2b9f7de9f5df101ea18bdb2b5bee5617ab4..f4764e270b90ae409badf21a0f88b2b408dcc0ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -74,11 +74,10 @@ JSObject* JSNotAnObject::toObject(ExecState* exec) const
 }
 
 // Marking
 }
 
 // Marking
-void JSNotAnObject::mark()
+void JSNotAnObject::markChildren(MarkStack& markStack)
 {
 {
-    JSCell::mark();
-    if (!m_exception->marked())
-        m_exception->mark();
+    JSObject::markChildren(markStack);
+    markStack.append(m_exception);
 }
 
 // JSObject methods
 }
 
 // JSObject methods
@@ -94,6 +93,12 @@ bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&)
     return false;
 }
 
     return false;
 }
 
+bool JSNotAnObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier&, PropertyDescriptor&)
+{
+    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    return false;
+}
+
 void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue, PutPropertySlot&)
 {
     ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
 void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue, PutPropertySlot&)
 {
     ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
@@ -116,7 +121,7 @@ bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned)
     return false;
 }
 
     return false;
 }
 
-void JSNotAnObject::getPropertyNames(ExecState* exec, PropertyNameArray&)
+void JSNotAnObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray&, EnumerationMode)
 {
     ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
 }
 {
     ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
 }
index a8e36bd21dbc96c9b90dc12a45ad1d6b4245845b..339d41f5a2294413c140ae9fdff58347f30fa6fb 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -62,10 +62,13 @@ namespace JSC {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType));
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
 
      private:
         }
 
      private:
+        
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
+
         // JSValue methods
         virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
         virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
         // JSValue methods
         virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
         virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
@@ -75,11 +78,12 @@ namespace JSC {
         virtual JSObject* toObject(ExecState*) const;
 
         // Marking
         virtual JSObject* toObject(ExecState*) const;
 
         // Marking
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         // JSObject methods
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
 
         // JSObject methods
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual void put(ExecState*, unsigned propertyName, JSValue);
 
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual void put(ExecState*, unsigned propertyName, JSValue);
@@ -87,7 +91,7 @@ namespace JSC {
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
         virtual bool deleteProperty(ExecState*, unsigned propertyName);
 
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
         virtual bool deleteProperty(ExecState*, unsigned propertyName);
 
-        virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
 
         JSNotAnObjectErrorStub* m_exception;
     };
 
         JSNotAnObjectErrorStub* m_exception;
     };
index 0654da75ea5ec6959eb2b31d622bd5a912de90e4..f1009b9c010983f9d9530b5ec0b34d73b20a51ef 100644 (file)
@@ -54,15 +54,11 @@ double JSNumberCell::toNumber(ExecState*) const
 
 UString JSNumberCell::toString(ExecState*) const
 {
 
 UString JSNumberCell::toString(ExecState*) const
 {
-    if (m_value == 0.0) // +0.0 or -0.0
-        return "0";
     return UString::from(m_value);
 }
 
 UString JSNumberCell::toThisString(ExecState*) const
 {
     return UString::from(m_value);
 }
 
 UString JSNumberCell::toThisString(ExecState*) const
 {
-    if (m_value == 0.0) // +0.0 or -0.0
-        return "0";
     return UString::from(m_value);
 }
 
     return UString::from(m_value);
 }
 
index 04cccefecb794160ecbf8f3a2d7e4f36fad98204..bcb506b97394016e86030eb0da05df207373813d 100644 (file)
@@ -68,23 +68,15 @@ namespace JSC {
 
         void* operator new(size_t size, ExecState* exec)
         {
 
         void* operator new(size_t size, ExecState* exec)
         {
-    #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
-            return exec->heap()->inlineAllocateNumber(size);
-    #else
             return exec->heap()->allocateNumber(size);
             return exec->heap()->allocateNumber(size);
-    #endif
         }
 
         void* operator new(size_t size, JSGlobalData* globalData)
         {
         }
 
         void* operator new(size_t size, JSGlobalData* globalData)
         {
-    #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
-            return globalData->heap.inlineAllocateNumber(size);
-    #else
             return globalData->heap.allocateNumber(size);
             return globalData->heap.allocateNumber(size);
-    #endif
         }
 
         }
 
-        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion)); }
+        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount); }
 
     private:
         JSNumberCell(JSGlobalData* globalData, double value)
 
     private:
         JSNumberCell(JSGlobalData* globalData, double value)
@@ -117,6 +109,11 @@ namespace JSC {
         return static_cast<JSNumberCell*>(v.asCell());
     }
 
         return static_cast<JSNumberCell*>(v.asCell());
     }
 
+    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState* exec, double d)
+    {
+        *this = jsNumberCell(exec, d);
+    }
+
     inline JSValue::JSValue(ExecState* exec, double d)
     {
         JSValue v = JSImmediate::from(d);
     inline JSValue::JSValue(ExecState* exec, double d)
     {
         JSValue v = JSImmediate::from(d);
@@ -201,6 +198,11 @@ namespace JSC {
 #endif // USE(JSVALUE32)
 
 #if USE(JSVALUE64)
 #endif // USE(JSVALUE32)
 
 #if USE(JSVALUE64)
+    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d)
+    {
+        *this = JSImmediate::fromNumberOutsideIntegerRange(d);
+    }
+
     inline JSValue::JSValue(ExecState*, double d)
     {
         JSValue v = JSImmediate::from(d);
     inline JSValue::JSValue(ExecState*, double d)
     {
         JSValue v = JSImmediate::from(d);
index 4a89c55c394835fe0a523f81f3cfffa275703f90..ce0dcffe0569565fe78a3d01d4113dda68627a5d 100644 (file)
@@ -32,6 +32,7 @@
 #include "JSArray.h"
 #include "LiteralParser.h"
 #include "PropertyNameArray.h"
 #include "JSArray.h"
 #include "LiteralParser.h"
 #include "PropertyNameArray.h"
+#include "StringBuilder.h"
 #include <wtf/MathExtras.h>
 
 namespace JSC {
 #include <wtf/MathExtras.h>
 
 namespace JSC {
@@ -61,17 +62,15 @@ private:
     mutable JSValue m_value;
 };
 
     mutable JSValue m_value;
 };
 
-class Stringifier : Noncopyable {
+class Stringifier : public Noncopyable {
 public:
     Stringifier(ExecState*, JSValue replacer, JSValue space);
     ~Stringifier();
     JSValue stringify(JSValue);
 
 public:
     Stringifier(ExecState*, JSValue replacer, JSValue space);
     ~Stringifier();
     JSValue stringify(JSValue);
 
-    void mark();
+    void markAggregate(MarkStack&);
 
 private:
 
 private:
-    typedef UString StringBuilder;
-
     class Holder {
     public:
         Holder(JSObject*);
     class Holder {
     public:
         Holder(JSObject*);
@@ -120,38 +119,47 @@ private:
 
 // ------------------------------ helper functions --------------------------------
 
 
 // ------------------------------ helper functions --------------------------------
 
-static inline JSValue unwrapBoxedPrimitive(JSValue value)
+static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value)
 {
     if (!value.isObject())
         return value;
 {
     if (!value.isObject())
         return value;
-    if (!asObject(value)->inherits(&NumberObject::info) && !asObject(value)->inherits(&StringObject::info) && !asObject(value)->inherits(&BooleanObject::info))
-        return value;
-    return static_cast<JSWrapperObject*>(asObject(value))->internalValue();
+    JSObject* object = asObject(value);
+    if (object->inherits(&NumberObject::info))
+        return jsNumber(exec, object->toNumber(exec));
+    if (object->inherits(&StringObject::info))
+        return jsString(exec, object->toString(exec));
+    if (object->inherits(&BooleanObject::info))
+        return object->toPrimitive(exec);
+    return value;
 }
 
 }
 
-static inline UString gap(JSValue space)
+static inline UString gap(ExecState* exec, JSValue space)
 {
 {
-    space = unwrapBoxedPrimitive(space);
+    const int maxGapLength = 10;
+    space = unwrapBoxedPrimitive(exec, space);
 
     // If the space value is a number, create a gap string with that number of spaces.
     double spaceCount;
     if (space.getNumber(spaceCount)) {
 
     // If the space value is a number, create a gap string with that number of spaces.
     double spaceCount;
     if (space.getNumber(spaceCount)) {
-        const int maxSpaceCount = 100;
         int count;
         int count;
-        if (spaceCount > maxSpaceCount)
-            count = maxSpaceCount;
+        if (spaceCount > maxGapLength)
+            count = maxGapLength;
         else if (!(spaceCount > 0))
             count = 0;
         else
             count = static_cast<int>(spaceCount);
         else if (!(spaceCount > 0))
             count = 0;
         else
             count = static_cast<int>(spaceCount);
-        UChar spaces[maxSpaceCount];
+        UChar spaces[maxGapLength];
         for (int i = 0; i < count; ++i)
             spaces[i] = ' ';
         return UString(spaces, count);
     }
 
     // If the space value is a string, use it as the gap string, otherwise use no gap string.
         for (int i = 0; i < count; ++i)
             spaces[i] = ' ';
         return UString(spaces, count);
     }
 
     // If the space value is a string, use it as the gap string, otherwise use no gap string.
-    return space.getString();
+    UString spaces = space.getString(exec);
+    if (spaces.size() > maxGapLength) {
+        spaces = spaces.substr(0, maxGapLength);
+    }
+    return spaces;
 }
 
 // ------------------------------ PropertyNameForFunctionCall --------------------------------
 }
 
 // ------------------------------ PropertyNameForFunctionCall --------------------------------
@@ -187,7 +195,7 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
     , m_usingArrayReplacer(false)
     , m_arrayReplacerPropertyNames(exec)
     , m_replacerCallType(CallTypeNone)
     , m_usingArrayReplacer(false)
     , m_arrayReplacerPropertyNames(exec)
     , m_replacerCallType(CallTypeNone)
-    , m_gap(gap(space))
+    , m_gap(gap(exec, space))
 {
     exec->globalData().firstStringifierToMark = this;
 
 {
     exec->globalData().firstStringifierToMark = this;
 
@@ -202,12 +210,27 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
             JSValue name = array->get(exec, i);
             if (exec->hadException())
                 break;
             JSValue name = array->get(exec, i);
             if (exec->hadException())
                 break;
+
             UString propertyName;
             UString propertyName;
-            if (!name.getString(propertyName))
+            if (name.getString(exec, propertyName)) {
+                m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
                 continue;
                 continue;
-            if (exec->hadException())
-                return;
-            m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
+            }
+
+            double value = 0;
+            if (name.getNumber(value)) {
+                m_arrayReplacerPropertyNames.add(Identifier::from(exec, value));
+                continue;
+            }
+
+            if (name.isObject()) {
+                if (!asObject(name)->inherits(&NumberObject::info) && !asObject(name)->inherits(&StringObject::info))
+                    continue;
+                propertyName = name.toString(exec);
+                if (exec->hadException())
+                    break;
+                m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
+            }
         }
         return;
     }
         }
         return;
     }
@@ -221,15 +244,12 @@ Stringifier::~Stringifier()
     m_exec->globalData().firstStringifierToMark = m_nextStringifierToMark;
 }
 
     m_exec->globalData().firstStringifierToMark = m_nextStringifierToMark;
 }
 
-void Stringifier::mark()
+void Stringifier::markAggregate(MarkStack& markStack)
 {
     for (Stringifier* stringifier = this; stringifier; stringifier = stringifier->m_nextStringifierToMark) {
         size_t size = m_holderStack.size();
 {
     for (Stringifier* stringifier = this; stringifier; stringifier = stringifier->m_nextStringifierToMark) {
         size_t size = m_holderStack.size();
-        for (size_t i = 0; i < size; ++i) {
-            JSObject* object = m_holderStack[i].object();
-            if (!object->marked())
-                object->mark();
-        }
+        for (size_t i = 0; i < size; ++i)
+            markStack.append(m_holderStack[i].object());
     }
 }
 
     }
 }
 
@@ -248,7 +268,7 @@ JSValue Stringifier::stringify(JSValue value)
     if (m_exec->hadException())
         return jsNull();
 
     if (m_exec->hadException())
         return jsNull();
 
-    return jsString(m_exec, result);
+    return jsString(m_exec, result.release());
 }
 
 void Stringifier::appendQuotedString(StringBuilder& builder, const UString& value)
 }
 
 void Stringifier::appendQuotedString(StringBuilder& builder, const UString& value)
@@ -339,8 +359,6 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
     value = toJSON(value, propertyName);
     if (m_exec->hadException())
         return StringifyFailed;
     value = toJSON(value, propertyName);
     if (m_exec->hadException())
         return StringifyFailed;
-    if (value.isUndefined() && !holder->inherits(&JSArray::info))
-        return StringifyFailedDueToUndefinedValue;
 
     // Call the replacer function.
     if (m_replacerCallType != CallTypeNone) {
 
     // Call the replacer function.
     if (m_replacerCallType != CallTypeNone) {
@@ -351,12 +369,18 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
             return StringifyFailed;
     }
 
             return StringifyFailed;
     }
 
+    if (value.isUndefined() && !holder->inherits(&JSArray::info))
+        return StringifyFailedDueToUndefinedValue;
+
     if (value.isNull()) {
         builder.append("null");
         return StringifySucceeded;
     }
 
     if (value.isNull()) {
         builder.append("null");
         return StringifySucceeded;
     }
 
-    value = unwrapBoxedPrimitive(value);
+    value = unwrapBoxedPrimitive(m_exec, value);
+
+    if (m_exec->hadException())
+        return StringifyFailed;
 
     if (value.isBoolean()) {
         builder.append(value.getBoolean() ? "true" : "false");
 
     if (value.isBoolean()) {
         builder.append(value.getBoolean() ? "true" : "false");
@@ -364,7 +388,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
     }
 
     UString stringValue;
     }
 
     UString stringValue;
-    if (value.getString(stringValue)) {
+    if (value.getString(m_exec, stringValue)) {
         appendQuotedString(builder, stringValue);
         return StringifySucceeded;
     }
         appendQuotedString(builder, stringValue);
         return StringifySucceeded;
     }
@@ -383,9 +407,18 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
 
     JSObject* object = asObject(value);
 
 
     JSObject* object = asObject(value);
 
+    CallData callData;
+    if (object->getCallData(callData) != CallTypeNone) {
+        if (holder->inherits(&JSArray::info)) {
+            builder.append("null");
+            return StringifySucceeded;
+        }
+        return StringifyFailedDueToUndefinedValue;
+    }
+
     // Handle cycle detection, and put the holder on the stack.
     if (!m_holderCycleDetector.add(object).second) {
     // Handle cycle detection, and put the holder on the stack.
     if (!m_holderCycleDetector.add(object).second) {
-        throwError(m_exec, TypeError);
+        throwError(m_exec, TypeError, "JSON.stringify cannot serialize cyclic structures.");
         return StringifyFailed;
     }
     bool holderStackWasEmpty = m_holderStack.isEmpty();
         return StringifyFailed;
     }
     bool holderStackWasEmpty = m_holderStack.isEmpty();
@@ -425,7 +458,7 @@ inline void Stringifier::indent()
     // Use a single shared string, m_repeatedGap, so we don't keep allocating new ones as we indent and unindent.
     int newSize = m_indent.size() + m_gap.size();
     if (newSize > m_repeatedGap.size())
     // Use a single shared string, m_repeatedGap, so we don't keep allocating new ones as we indent and unindent.
     int newSize = m_indent.size() + m_gap.size();
     if (newSize > m_repeatedGap.size())
-        m_repeatedGap.append(m_gap);
+        m_repeatedGap = makeString(m_repeatedGap, m_gap);
     ASSERT(newSize <= m_repeatedGap.size());
     m_indent = m_repeatedGap.substr(0, newSize);
 }
     ASSERT(newSize <= m_repeatedGap.size());
     m_indent = m_repeatedGap.substr(0, newSize);
 }
@@ -468,7 +501,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
                 m_propertyNames = stringifier.m_arrayReplacerPropertyNames.data();
             else {
                 PropertyNameArray objectPropertyNames(exec);
                 m_propertyNames = stringifier.m_arrayReplacerPropertyNames.data();
             else {
                 PropertyNameArray objectPropertyNames(exec);
-                m_object->getPropertyNames(exec, objectPropertyNames);
+                m_object->getOwnPropertyNames(exec, objectPropertyNames);
                 m_propertyNames = objectPropertyNames.releaseData();
             }
             m_size = m_propertyNames->propertyNameVector().size();
                 m_propertyNames = objectPropertyNames.releaseData();
             }
             m_size = m_propertyNames->propertyNameVector().size();
@@ -552,7 +585,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
             // This only occurs when get an undefined value for an object property.
             // In this case we don't want the separator and property name that we
             // already appended, so roll back.
             // This only occurs when get an undefined value for an object property.
             // In this case we don't want the separator and property name that we
             // already appended, so roll back.
-            builder = builder.substr(0, rollBackPoint);
+            builder.resize(rollBackPoint);
             break;
     }
 
             break;
     }
 
@@ -574,18 +607,17 @@ const ClassInfo JSONObject::info = { "JSON", 0, 0, ExecState::jsonTable };
 
 bool JSONObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 
 bool JSONObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    const HashEntry* entry = ExecState::jsonTable(exec)->entry(exec, propertyName);
-    if (!entry)
-        return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+    return getStaticFunctionSlot<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, slot);
+}
 
 
-    ASSERT(entry->attributes() & Function);
-    setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
-    return true;
+bool JSONObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor);
 }
 
 }
 
-void JSONObject::markStringifiers(Stringifier* stringifier)
+void JSONObject::markStringifiers(MarkStack& markStack, Stringifier* stringifier)
 {
 {
-    stringifier->mark();
+    stringifier->markAggregate(markStack);
 }
 
 class Walker {
 }
 
 class Walker {
@@ -599,11 +631,11 @@ public:
     }
     JSValue walk(JSValue unfiltered);
 private:
     }
     JSValue walk(JSValue unfiltered);
 private:
-    JSValue callReviver(JSValue property, JSValue unfiltered)
+    JSValue callReviver(JSObject* thisObj, JSValue property, JSValue unfiltered)
     {
         JSValue args[] = { property, unfiltered };
         ArgList argList(args, 2);
     {
         JSValue args[] = { property, unfiltered };
         ArgList argList(args, 2);
-        return call(m_exec, m_function, m_callType, m_callData, jsNull(), argList);
+        return call(m_exec, m_function, m_callType, m_callData, thisObj, argList);
     }
 
     friend class Holder;
     }
 
     friend class Holder;
@@ -613,7 +645,10 @@ private:
     CallType m_callType;
     CallData m_callData;
 };
     CallType m_callType;
     CallData m_callData;
 };
-    
+
+// We clamp recursion well beyond anything reasonable, but we also have a timeout check
+// to guard against "infinite" execution by inserting arbitrarily large objects.
+static const unsigned maximumFilterRecursion = 40000;
 enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember, 
                                  ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
 NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
 enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember, 
                                  ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
 NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
@@ -627,12 +662,21 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
     WalkerState state = StateUnknown;
     JSValue inValue = unfiltered;
     JSValue outValue = jsNull();
     WalkerState state = StateUnknown;
     JSValue inValue = unfiltered;
     JSValue outValue = jsNull();
+    
+    TimeoutChecker localTimeoutChecker(m_exec->globalData().timeoutChecker);
+    localTimeoutChecker.reset();
+    unsigned tickCount = localTimeoutChecker.ticksUntilNextCheck();
     while (1) {
         switch (state) {
             arrayStartState:
             case ArrayStartState: {
                 ASSERT(inValue.isObject());
     while (1) {
         switch (state) {
             arrayStartState:
             case ArrayStartState: {
                 ASSERT(inValue.isObject());
-                ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)));
+                ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)) || asObject(inValue)->inherits(&JSArray::info));
+                if (objectStack.size() + arrayStack.size() > maximumFilterRecursion) {
+                    m_exec->setException(createStackOverflowError(m_exec));
+                    return jsUndefined();
+                }
+
                 JSArray* array = asArray(inValue);
                 arrayStack.append(array);
                 indexStack.append(0);
                 JSArray* array = asArray(inValue);
                 arrayStack.append(array);
                 indexStack.append(0);
@@ -640,6 +684,14 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             }
             arrayStartVisitMember:
             case ArrayStartVisitMember: {
             }
             arrayStartVisitMember:
             case ArrayStartVisitMember: {
+                if (!--tickCount) {
+                    if (localTimeoutChecker.didTimeOut(m_exec)) {
+                        m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
+                        return jsUndefined();
+                    }
+                    tickCount = localTimeoutChecker.ticksUntilNextCheck();
+                }
+
                 JSArray* array = arrayStack.last();
                 uint32_t index = indexStack.last();
                 if (index == array->length()) {
                 JSArray* array = arrayStack.last();
                 uint32_t index = indexStack.last();
                 if (index == array->length()) {
@@ -648,7 +700,16 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                     indexStack.removeLast();
                     break;
                 }
                     indexStack.removeLast();
                     break;
                 }
-                inValue = array->getIndex(index);
+                if (isJSArray(&m_exec->globalData(), array) && array->canGetIndex(index))
+                    inValue = array->getIndex(index);
+                else {
+                    PropertySlot slot;
+                    if (array->getOwnPropertySlot(m_exec, index, slot))
+                        inValue = slot.getValue(m_exec, index);
+                    else
+                        inValue = jsUndefined();
+                }
+                    
                 if (inValue.isObject()) {
                     stateStack.append(ArrayEndVisitMember);
                     goto stateUnknown;
                 if (inValue.isObject()) {
                     stateStack.append(ArrayEndVisitMember);
                     goto stateUnknown;
@@ -658,7 +719,15 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             }
             case ArrayEndVisitMember: {
                 JSArray* array = arrayStack.last();
             }
             case ArrayEndVisitMember: {
                 JSArray* array = arrayStack.last();
-                array->setIndex(indexStack.last(), callReviver(jsString(m_exec, UString::from(indexStack.last())), outValue));
+                JSValue filteredValue = callReviver(array, jsString(m_exec, UString::from(indexStack.last())), outValue);
+                if (filteredValue.isUndefined())
+                    array->deleteProperty(m_exec, indexStack.last());
+                else {
+                    if (isJSArray(&m_exec->globalData(), array) && array->canSetIndex(indexStack.last()))
+                        array->setIndex(indexStack.last(), filteredValue);
+                    else
+                        array->put(m_exec, indexStack.last(), filteredValue);
+                }
                 if (m_exec->hadException())
                     return jsNull();
                 indexStack.last()++;
                 if (m_exec->hadException())
                     return jsNull();
                 indexStack.last()++;
@@ -667,16 +736,29 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             objectStartState:
             case ObjectStartState: {
                 ASSERT(inValue.isObject());
             objectStartState:
             case ObjectStartState: {
                 ASSERT(inValue.isObject());
-                ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)));
+                ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)) && !asObject(inValue)->inherits(&JSArray::info));
+                if (objectStack.size() + arrayStack.size() > maximumFilterRecursion) {
+                    m_exec->setException(createStackOverflowError(m_exec));
+                    return jsUndefined();
+                }
+
                 JSObject* object = asObject(inValue);
                 objectStack.append(object);
                 indexStack.append(0);
                 propertyStack.append(PropertyNameArray(m_exec));
                 JSObject* object = asObject(inValue);
                 objectStack.append(object);
                 indexStack.append(0);
                 propertyStack.append(PropertyNameArray(m_exec));
-                object->getPropertyNames(m_exec, propertyStack.last());
+                object->getOwnPropertyNames(m_exec, propertyStack.last());
                 // fallthrough
             }
             objectStartVisitMember:
             case ObjectStartVisitMember: {
                 // fallthrough
             }
             objectStartVisitMember:
             case ObjectStartVisitMember: {
+                if (!--tickCount) {
+                    if (localTimeoutChecker.didTimeOut(m_exec)) {
+                        m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
+                        return jsUndefined();
+                    }
+                    tickCount = localTimeoutChecker.ticksUntilNextCheck();
+                }
+
                 JSObject* object = objectStack.last();
                 uint32_t index = indexStack.last();
                 PropertyNameArray& properties = propertyStack.last();
                 JSObject* object = objectStack.last();
                 uint32_t index = indexStack.last();
                 PropertyNameArray& properties = propertyStack.last();
@@ -688,9 +770,15 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                     break;
                 }
                 PropertySlot slot;
                     break;
                 }
                 PropertySlot slot;
-                object->getOwnPropertySlot(m_exec, properties[index], slot);
-                inValue = slot.getValue(m_exec, properties[index]);
-                ASSERT(!m_exec->hadException());
+                if (object->getOwnPropertySlot(m_exec, properties[index], slot))
+                    inValue = slot.getValue(m_exec, properties[index]);
+                else
+                    inValue = jsUndefined();
+
+                // The holder may be modified by the reviver function so any lookup may throw
+                if (m_exec->hadException())
+                    return jsNull();
+
                 if (inValue.isObject()) {
                     stateStack.append(ObjectEndVisitMember);
                     goto stateUnknown;
                 if (inValue.isObject()) {
                     stateStack.append(ObjectEndVisitMember);
                     goto stateUnknown;
@@ -702,7 +790,11 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 JSObject* object = objectStack.last();
                 Identifier prop = propertyStack.last()[indexStack.last()];
                 PutPropertySlot slot;
                 JSObject* object = objectStack.last();
                 Identifier prop = propertyStack.last()[indexStack.last()];
                 PutPropertySlot slot;
-                object->put(m_exec, prop, callReviver(jsString(m_exec, prop.ustring()), outValue), slot);
+                JSValue filteredValue = callReviver(object, jsString(m_exec, prop.ustring()), outValue);
+                if (filteredValue.isUndefined())
+                    object->deleteProperty(m_exec, prop);
+                else
+                    object->put(m_exec, prop, filteredValue, slot);
                 if (m_exec->hadException())
                     return jsNull();
                 indexStack.last()++;
                 if (m_exec->hadException())
                     return jsNull();
                 indexStack.last()++;
@@ -714,16 +806,29 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                     outValue = inValue;
                     break;
                 }
                     outValue = inValue;
                     break;
                 }
-                if (isJSArray(&m_exec->globalData(), asObject(inValue)))
+                JSObject* object = asObject(inValue);
+                if (isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::info))
                     goto arrayStartState;
                 goto objectStartState;
         }
         if (stateStack.isEmpty())
             break;
                     goto arrayStartState;
                 goto objectStartState;
         }
         if (stateStack.isEmpty())
             break;
+
         state = stateStack.last();
         stateStack.removeLast();
         state = stateStack.last();
         stateStack.removeLast();
+
+        if (!--tickCount) {
+            if (localTimeoutChecker.didTimeOut(m_exec)) {
+                m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
+                return jsUndefined();
+            }
+            tickCount = localTimeoutChecker.ticksUntilNextCheck();
+        }
     }
     }
-    return callReviver(jsEmptyString(m_exec), outValue);
+    JSObject* finalHolder = constructEmptyObject(m_exec);
+    PutPropertySlot slot;
+    finalHolder->put(m_exec, m_exec->globalData().propertyNames->emptyIdentifier, outValue, slot);
+    return callReviver(finalHolder, jsEmptyString(m_exec), outValue);
 }
 
 // ECMA-262 v5 15.12.2
 }
 
 // ECMA-262 v5 15.12.2
index 8d5364a36571e47dddb6c120714dc2452fa9f950..905e4bc0e0e21cd5f4ee1104b756688430f5e10b 100644 (file)
@@ -34,20 +34,24 @@ namespace JSC {
 
     class JSONObject : public JSObject {
     public:
 
     class JSONObject : public JSObject {
     public:
-        JSONObject(PassRefPtr<Structure> structure)
+        JSONObject(NonNullPassRefPtr<Structure> structure)
             : JSObject(structure)
         {
         }
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
             : JSObject(structure)
         {
         }
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType));
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
 
         }
 
-        static void markStringifiers(Stringifier*);
+        static void markStringifiers(MarkStack&, Stringifier*);
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
 
     private:
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
 
     private:
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
index b13f143a6ec0834e47a95968c554c59a8739d51b..d9500aa5a98d376122f026a00217c831ff602c2f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Eric Seidel (eric@webkit.org)
  *
  *  This library is free software; you can redistribute it and/or
  *  Copyright (C) 2007 Eric Seidel (eric@webkit.org)
  *
  *  This library is free software; you can redistribute it and/or
@@ -30,6 +30,7 @@
 #include "JSGlobalObject.h"
 #include "NativeErrorConstructor.h"
 #include "ObjectPrototype.h"
 #include "JSGlobalObject.h"
 #include "NativeErrorConstructor.h"
 #include "ObjectPrototype.h"
+#include "PropertyDescriptor.h"
 #include "PropertyNameArray.h"
 #include "Lookup.h"
 #include "Nodes.h"
 #include "PropertyNameArray.h"
 #include "Lookup.h"
 #include "Nodes.h"
 #include <math.h>
 #include <wtf/Assertions.h>
 
 #include <math.h>
 #include <wtf/Assertions.h>
 
-#define JSOBJECT_MARK_TRACING 0
-
-#if JSOBJECT_MARK_TRACING
-
-#define JSOBJECT_MARK_BEGIN() \
-    static int markStackDepth = 0; \
-    for (int i = 0; i < markStackDepth; i++) \
-        putchar('-'); \
-    printf("%s (%p)\n", className().UTF8String().c_str(), this); \
-    markStackDepth++; \
-
-#define JSOBJECT_MARK_END() \
-    markStackDepth--;
-
-#else // JSOBJECT_MARK_TRACING
-
-#define JSOBJECT_MARK_BEGIN()
-#define JSOBJECT_MARK_END()
-
-#endif // JSOBJECT_MARK_TRACING
-
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSObject);
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSObject);
 
-void JSObject::mark()
-{
-    JSOBJECT_MARK_BEGIN();
-
-    JSCell::mark();
-    m_structure->mark();
+static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    // Add properties from the static hashtables of properties
+    for (; classInfo; classInfo = classInfo->parentClass) {
+        const HashTable* table = classInfo->propHashTable(exec);
+        if (!table)
+            continue;
+        table->initializeIfNeeded(exec);
+        ASSERT(table->table);
+
+        int hashSizeMask = table->compactSize - 1;
+        const HashEntry* entry = table->table;
+        for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
+            if (entry->key() && (!(entry->attributes() & DontEnum) || (mode == IncludeDontEnumProperties)))
+                propertyNames.add(entry->key());
+        }
+    }
+}
 
 
-    PropertyStorage storage = propertyStorage();
+void JSObject::markChildren(MarkStack& markStack)
+{
+#ifndef NDEBUG
+    bool wasCheckingForDefaultMarkViolation = markStack.m_isCheckingForDefaultMarkViolation;
+    markStack.m_isCheckingForDefaultMarkViolation = false;
+#endif
 
 
-    size_t storageSize = m_structure->propertyStorageSize();
-    for (size_t i = 0; i < storageSize; ++i) {
-        JSValue v = JSValue::decode(storage[i]);
-        if (!v.marked())
-            v.mark();
-    }
+    markChildrenDirect(markStack);
 
 
-    JSOBJECT_MARK_END();
+#ifndef NDEBUG
+    markStack.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
+#endif
 }
 
 UString JSObject::className() const
 }
 
 UString JSObject::className() const
@@ -300,7 +294,7 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi
     return 0;
 }
 
     return 0;
 }
 
-void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
 {
     JSValue object = getDirect(propertyName);
     if (object && object.isGetterSetter()) {
 {
     JSValue object = getDirect(propertyName);
     if (object && object.isGetterSetter()) {
@@ -310,8 +304,8 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO
     }
 
     PutPropertySlot slot;
     }
 
     PutPropertySlot slot;
-    GetterSetter* getterSetter = new (exec) GetterSetter;
-    putDirectInternal(exec->globalData(), propertyName, getterSetter, Getter, true, slot);
+    GetterSetter* getterSetter = new (exec) GetterSetter(exec);
+    putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Getter, true, slot);
 
     // putDirect will change our Structure if we add a new property. For
     // getters and setters, though, we also need to change our Structure
 
     // putDirect will change our Structure if we add a new property. For
     // getters and setters, though, we also need to change our Structure
@@ -327,7 +321,7 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO
     getterSetter->setGetter(getterFunction);
 }
 
     getterSetter->setGetter(getterFunction);
 }
 
-void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
+void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
 {
     JSValue object = getDirect(propertyName);
     if (object && object.isGetterSetter()) {
 {
     JSValue object = getDirect(propertyName);
     if (object && object.isGetterSetter()) {
@@ -337,8 +331,8 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO
     }
 
     PutPropertySlot slot;
     }
 
     PutPropertySlot slot;
-    GetterSetter* getterSetter = new (exec) GetterSetter;
-    putDirectInternal(exec->globalData(), propertyName, getterSetter, Setter, true, slot);
+    GetterSetter* getterSetter = new (exec) GetterSetter(exec);
+    putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Setter, true, slot);
 
     // putDirect will change our Structure if we add a new property. For
     // getters and setters, though, we also need to change our Structure
 
     // putDirect will change our Structure if we add a new property. For
     // getters and setters, though, we also need to change our Structure
@@ -412,26 +406,10 @@ bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue proto)
 
 bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const
 {
 
 bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const
 {
-    unsigned attributes;
-    if (!getPropertyAttributes(exec, propertyName, attributes))
+    PropertyDescriptor descriptor;
+    if (!const_cast<JSObject*>(this)->getOwnPropertyDescriptor(exec, propertyName, descriptor))
         return false;
         return false;
-    return !(attributes & DontEnum);
-}
-
-bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
-{
-    JSCell* specificValue;
-    if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound)
-        return true;
-    
-    // Look in the static hashtable of properties
-    const HashEntry* entry = findPropertyHashEntry(exec, propertyName);
-    if (entry) {
-        attributes = entry->attributes();
-        return true;
-    }
-    
-    return false;
+    return descriptor.enumerable();
 }
 
 bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyName, JSCell*& specificValue) const
 }
 
 bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyName, JSCell*& specificValue) const
@@ -447,9 +425,31 @@ bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyNa
     return false;
 }
 
     return false;
 }
 
-void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    m_structure->getEnumerablePropertyNames(exec, propertyNames, this);
+    getOwnPropertyNames(exec, propertyNames, mode);
+
+    if (prototype().isNull())
+        return;
+
+    JSObject* prototype = asObject(this->prototype());
+    while(1) {
+        if (prototype->structure()->typeInfo().overridesGetPropertyNames()) {
+            prototype->getPropertyNames(exec, propertyNames, mode);
+            break;
+        }
+        prototype->getOwnPropertyNames(exec, propertyNames, mode);
+        JSValue nextProto = prototype->prototype();
+        if (nextProto.isNull())
+            break;
+        prototype = asObject(nextProto);
+    }
+}
+
+void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    m_structure->getPropertyNames(propertyNames, mode);
+    getClassPropertyNames(exec, classInfo(), propertyNames, mode);
 }
 
 bool JSObject::toBoolean(ExecState*) const
 }
 
 bool JSObject::toBoolean(ExecState*) const
@@ -506,12 +506,12 @@ void JSObject::removeDirect(const Identifier& propertyName)
 
 void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr)
 {
 
 void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr)
 {
-    putDirectFunction(Identifier(exec, function->name(&exec->globalData())), function, attr);
+    putDirectFunction(Identifier(exec, function->name(exec)), function, attr);
 }
 
 void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr)
 {
 }
 
 void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr)
 {
-    putDirectFunctionWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr);
+    putDirectFunctionWithoutTransition(Identifier(exec, function->name(exec)), function, attr);
 }
 
 NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue* location)
 }
 
 NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue* location)
@@ -533,9 +533,154 @@ void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
     allocatePropertyStorageInline(oldSize, newSize);
 }
 
     allocatePropertyStorageInline(oldSize, newSize);
 }
 
-JSObject* constructEmptyObject(ExecState* exec)
+bool JSObject::getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+    unsigned attributes = 0;
+    JSCell* cell = 0;
+    size_t offset = m_structure->get(propertyName, attributes, cell);
+    if (offset == WTF::notFound)
+        return false;
+    descriptor.setDescriptor(getDirectOffset(offset), attributes);
+    return true;
+}
+
+bool JSObject::getPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    JSObject* object = this;
+    while (true) {
+        if (object->getOwnPropertyDescriptor(exec, propertyName, descriptor))
+            return true;
+        JSValue prototype = object->prototype();
+        if (!prototype.isObject())
+            return false;
+        object = asObject(prototype);
+    }
+}
+
+static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, JSValue oldValue)
+{
+    if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) {
+        target->putWithAttributes(exec, propertyName, descriptor.value() ? descriptor.value() : oldValue, attributes & ~(Getter | Setter));
+        return true;
+    }
+    attributes &= ~ReadOnly;
+    if (descriptor.getter() && descriptor.getter().isObject())
+        target->defineGetter(exec, propertyName, asObject(descriptor.getter()), attributes);
+    if (exec->hadException())
+        return false;
+    if (descriptor.setter() && descriptor.setter().isObject())
+        target->defineSetter(exec, propertyName, asObject(descriptor.setter()), attributes);
+    return !exec->hadException();
+}
+
+bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
+{
+    // If we have a new property we can just put it on normally
+    PropertyDescriptor current;
+    if (!getOwnPropertyDescriptor(exec, propertyName, current))
+        return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), jsUndefined());
+
+    if (descriptor.isEmpty())
+        return true;
+
+    if (current.equalTo(exec, descriptor))
+        return true;
+
+    // Filter out invalid changes
+    if (!current.configurable()) {
+        if (descriptor.configurable()) {
+            if (throwException)
+                throwError(exec, TypeError, "Attempting to configurable attribute of unconfigurable property.");
+            return false;
+        }
+        if (descriptor.enumerablePresent() && descriptor.enumerable() != current.enumerable()) {
+            if (throwException)
+                throwError(exec, TypeError, "Attempting to change enumerable attribute of unconfigurable property.");
+            return false;
+        }
+    }
+
+    // A generic descriptor is simply changing the attributes of an existing property
+    if (descriptor.isGenericDescriptor()) {
+        if (!current.attributesEqual(descriptor)) {
+            deleteProperty(exec, propertyName);
+            putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
+        }
+        return true;
+    }
+
+    // Changing between a normal property or an accessor property
+    if (descriptor.isDataDescriptor() != current.isDataDescriptor()) {
+        if (!current.configurable()) {
+            if (throwException)
+                throwError(exec, TypeError, "Attempting to change access mechanism for an unconfigurable property.");
+            return false;
+        }
+        deleteProperty(exec, propertyName);
+        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value() ? current.value() : jsUndefined());
+    }
+
+    // Changing the value and attributes of an existing property
+    if (descriptor.isDataDescriptor()) {
+        if (!current.configurable()) {
+            if (!current.writable() && descriptor.writable()) {
+                if (throwException)
+                    throwError(exec, TypeError, "Attempting to change writable attribute of unconfigurable property.");
+                return false;
+            }
+            if (!current.writable()) {
+                if (descriptor.value() || !JSValue::strictEqual(exec, current.value(), descriptor.value())) {
+                    if (throwException)
+                        throwError(exec, TypeError, "Attempting to change value of a readonly property.");
+                    return false;
+                }
+            }
+        } else if (current.attributesEqual(descriptor)) {
+            if (!descriptor.value())
+                return true;
+            PutPropertySlot slot;
+            put(exec, propertyName, descriptor.value(), slot);
+            if (exec->hadException())
+                return false;
+            return true;
+        }
+        deleteProperty(exec, propertyName);
+        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
+    }
+
+    // Changing the accessor functions of an existing accessor property
+    ASSERT(descriptor.isAccessorDescriptor());
+    if (!current.configurable()) {
+        if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) {
+            if (throwException)
+                throwError(exec, TypeError, "Attempting to change the setter of an unconfigurable property.");
+            return false;
+        }
+        if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) {
+            if (throwException)
+                throwError(exec, TypeError, "Attempting to change the getter of an unconfigurable property.");
+            return false;
+        }
+    }
+    JSValue accessor = getDirect(propertyName);
+    if (!accessor)
+        return false;
+    GetterSetter* getterSetter = asGetterSetter(accessor);
+    if (current.attributesEqual(descriptor)) {
+        if (descriptor.setter())
+            getterSetter->setSetter(asObject(descriptor.setter()));
+        if (descriptor.getter())
+            getterSetter->setGetter(asObject(descriptor.getter()));
+        return true;
+    }
+    deleteProperty(exec, propertyName);
+    unsigned attrs = current.attributesWithOverride(descriptor);
+    if (descriptor.setter())
+        attrs |= Setter;
+    if (descriptor.getter())
+        attrs |= Getter;
+    putDirect(propertyName, getterSetter, attrs);
+    return true;
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index ac4706fb931b04f5ebc0243a186bea1b229e5634..2b31a65994a0c334ff12e70ea3e4064b698c9f10 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -27,7 +27,9 @@
 #include "ClassInfo.h"
 #include "CommonIdentifiers.h"
 #include "CallFrame.h"
 #include "ClassInfo.h"
 #include "CommonIdentifiers.h"
 #include "CallFrame.h"
+#include "JSCell.h"
 #include "JSNumberCell.h"
 #include "JSNumberCell.h"
+#include "MarkStack.h"
 #include "PropertySlot.h"
 #include "PutPropertySlot.h"
 #include "ScopeChain.h"
 #include "PropertySlot.h"
 #include "PutPropertySlot.h"
 #include "ScopeChain.h"
@@ -43,11 +45,12 @@ namespace JSC {
             return value.asCell();
         return 0;
     }
             return value.asCell();
         return 0;
     }
-
+    
+    class HashEntry;
     class InternalFunction;
     class InternalFunction;
+    class PropertyDescriptor;
     class PropertyNameArray;
     class Structure;
     class PropertyNameArray;
     class Structure;
-    struct HashEntry;
     struct HashTable;
 
     // ECMA 262-3 8.6.1
     struct HashTable;
 
     // ECMA 262-3 8.6.1
@@ -71,20 +74,19 @@ namespace JSC {
         friend class JSCell;
 
     public:
         friend class JSCell;
 
     public:
-        explicit JSObject(PassRefPtr<Structure>);
+        explicit JSObject(NonNullPassRefPtr<Structure>);
 
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
+        ALWAYS_INLINE void markChildrenDirect(MarkStack& markStack);
 
         // The inline virtual destructor cannot be the first virtual function declared
         // in the class as it results in the vtable being generated as a weak symbol
         virtual ~JSObject();
 
 
         // The inline virtual destructor cannot be the first virtual function declared
         // in the class as it results in the vtable being generated as a weak symbol
         virtual ~JSObject();
 
-        bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); }
-
         JSValue prototype() const;
         void setPrototype(JSValue prototype);
         
         JSValue prototype() const;
         void setPrototype(JSValue prototype);
         
-        void setStructure(PassRefPtr<Structure>);
+        void setStructure(NonNullPassRefPtr<Structure>);
         Structure* inheritorID();
 
         virtual UString className() const;
         Structure* inheritorID();
 
         virtual UString className() const;
@@ -94,9 +96,11 @@ namespace JSC {
 
         bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
 
         bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+        bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         virtual void put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&);
         virtual void put(ExecState*, unsigned propertyName, JSValue value);
 
         virtual void put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&);
         virtual void put(ExecState*, unsigned propertyName, JSValue value);
@@ -118,7 +122,8 @@ namespace JSC {
 
         virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty);
 
 
         virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty);
 
-        virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+        virtual void getPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
 
         virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
         virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
 
         virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
         virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
@@ -130,7 +135,6 @@ namespace JSC {
         virtual JSObject* toThisObject(ExecState*) const;
         virtual JSObject* unwrappedObject();
 
         virtual JSObject* toThisObject(ExecState*) const;
         virtual JSObject* unwrappedObject();
 
-        virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
         bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const;
 
         // This get function only looks at the property map.
         bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const;
 
         // This get function only looks at the property map.
@@ -181,10 +185,11 @@ namespace JSC {
 
         void fillGetterPropertySlot(PropertySlot&, JSValue* location);
 
 
         void fillGetterPropertySlot(PropertySlot&, JSValue* location);
 
-        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
-        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
+        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0);
+        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0);
         virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
         virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
         virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
         virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
+        virtual bool defineOwnProperty(ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
 
         virtual bool isGlobalObject() const { return false; }
         virtual bool isVariableObject() const { return false; }
 
         virtual bool isGlobalObject() const { return false; }
         virtual bool isVariableObject() const { return false; }
@@ -196,12 +201,12 @@ namespace JSC {
         void allocatePropertyStorageInline(size_t oldSize, size_t newSize);
         bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); }
 
         void allocatePropertyStorageInline(size_t oldSize, size_t newSize);
         bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); }
 
-        static const size_t inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3;
-        static const size_t nonInlineBaseStorageCapacity = 16;
+        static const unsigned inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3;
+        static const unsigned nonInlineBaseStorageCapacity = 16;
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
 
         void flattenDictionaryObject()
         }
 
         void flattenDictionaryObject()
@@ -209,7 +214,33 @@ namespace JSC {
             m_structure->flattenDictionaryStructure(this);
         }
 
             m_structure->flattenDictionaryStructure(this);
         }
 
+    protected:
+        static const unsigned StructureFlags = 0;
+
+        void putAnonymousValue(unsigned index, JSValue value)
+        {
+            ASSERT(index < m_structure->anonymousSlotCount());
+            *locationForOffset(index) = value;
+        }
+        JSValue getAnonymousValue(unsigned index) const
+        {
+            ASSERT(index < m_structure->anonymousSlotCount());
+            return *locationForOffset(index);
+        }
+
     private:
     private:
+        // Nobody should ever ask any of these questions on something already known to be a JSObject.
+        using JSCell::isAPIValueWrapper;
+        using JSCell::isGetterSetter;
+        using JSCell::toObject;
+        void getObject();
+        void getString(ExecState* exec);
+        void isObject();
+        void isString();
+#if USE(JSVALUE32)
+        void isNumber();
+#endif
+
         ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
         PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
 
         ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
         PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
 
@@ -240,18 +271,20 @@ namespace JSC {
         RefPtr<Structure> m_inheritorID;
     };
     
         RefPtr<Structure> m_inheritorID;
     };
     
-JSObject* constructEmptyObject(ExecState*);
+inline JSObject* asObject(JSCell* cell)
+{
+    ASSERT(cell->isObject());
+    return static_cast<JSObject*>(cell);
+}
 
 inline JSObject* asObject(JSValue value)
 {
 
 inline JSObject* asObject(JSValue value)
 {
-    ASSERT(asCell(value)->isObject());
-    return static_cast<JSObject*>(asCell(value));
+    return asObject(value.asCell());
 }
 
 }
 
-inline JSObject::JSObject(PassRefPtr<Structure> structure)
+inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure)
     : JSCell(structure.releaseRef()) // ~JSObject balances this ref()
 {
     : JSCell(structure.releaseRef()) // ~JSObject balances this ref()
 {
-    ASSERT(m_structure);
     ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity);
     ASSERT(m_structure->isEmpty());
     ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
     ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity);
     ASSERT(m_structure->isEmpty());
     ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
@@ -280,7 +313,7 @@ inline void JSObject::setPrototype(JSValue prototype)
     setStructure(newStructure.release());
 }
 
     setStructure(newStructure.release());
 }
 
-inline void JSObject::setStructure(PassRefPtr<Structure> structure)
+inline void JSObject::setStructure(NonNullPassRefPtr<Structure> structure)
 {
     m_structure->deref();
     m_structure = structure.releaseRef(); // ~JSObject balances this ref()
 {
     m_structure->deref();
     m_structure = structure.releaseRef(); // ~JSObject balances this ref()
@@ -298,7 +331,7 @@ inline bool Structure::isUsingInlineStorage() const
     return (propertyStorageCapacity() == JSObject::inlineStorageCapacity);
 }
 
     return (propertyStorageCapacity() == JSObject::inlineStorageCapacity);
 }
 
-inline bool JSCell::isObject(const ClassInfo* info) const
+inline bool JSCell::inherits(const ClassInfo* info) const
 {
     for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) {
         if (ci == info)
 {
     for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) {
         if (ci == info)
@@ -307,10 +340,10 @@ inline bool JSCell::isObject(const ClassInfo* info) const
     return false;
 }
 
     return false;
 }
 
-// this method is here to be after the inline declaration of JSCell::isObject
-inline bool JSValue::isObject(const ClassInfo* classInfo) const
+// this method is here to be after the inline declaration of JSCell::inherits
+inline bool JSValue::inherits(const ClassInfo* classInfo) const
 {
 {
-    return isCell() && asCell()->isObject(classInfo);
+    return isCell() && asCell()->inherits(classInfo);
 }
 
 ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 }
 
 ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -342,14 +375,14 @@ ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifie
 
 ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 
 ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    if (structure()->typeInfo().hasStandardGetOwnPropertySlot())
+    if (!structure()->typeInfo().overridesGetOwnPropertySlot())
         return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot);
     return getOwnPropertySlot(exec, propertyName, slot);
 }
 
 // It may seem crazy to inline a function this large but it makes a big difference
 // since this is function very hot in variable lookup
         return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot);
     return getOwnPropertySlot(exec, propertyName, slot);
 }
 
 // It may seem crazy to inline a function this large but it makes a big difference
 // since this is function very hot in variable lookup
-inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     JSObject* object = this;
     while (true) {
 {
     JSObject* object = this;
     while (true) {
@@ -362,7 +395,7 @@ inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propert
     }
 }
 
     }
 }
 
-inline bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
 {
     JSObject* object = this;
     while (true) {
 {
     JSObject* object = this;
     while (true) {
@@ -571,8 +604,7 @@ inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, Pro
     while (true) {
         if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
             return slot.getValue(exec, propertyName);
     while (true) {
         if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
             return slot.getValue(exec, propertyName);
-        ASSERT(cell->isObject());
-        JSValue prototype = static_cast<JSObject*>(cell)->prototype();
+        JSValue prototype = asObject(cell)->prototype();
         if (!prototype.isObject())
             return jsUndefined();
         cell = asObject(prototype);
         if (!prototype.isObject())
             return jsUndefined();
         cell = asObject(prototype);
@@ -597,8 +629,7 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot
     while (true) {
         if (cell->getOwnPropertySlot(exec, propertyName, slot))
             return slot.getValue(exec, propertyName);
     while (true) {
         if (cell->getOwnPropertySlot(exec, propertyName, slot))
             return slot.getValue(exec, propertyName);
-        ASSERT(cell->isObject());
-        JSValue prototype = static_cast<JSObject*>(cell)->prototype();
+        JSValue prototype = asObject(cell)->prototype();
         if (!prototype.isObject())
             return jsUndefined();
         cell = prototype.asCell();
         if (!prototype.isObject())
             return jsUndefined();
         cell = prototype.asCell();
@@ -643,6 +674,17 @@ ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_
     m_externalStorage = newPropertyStorage;
 }
 
     m_externalStorage = newPropertyStorage;
 }
 
+ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack)
+{
+    JSCell::markChildren(markStack);
+
+    markStack.append(prototype());
+    
+    PropertyStorage storage = propertyStorage();
+    size_t storageSize = m_structure->propertyStorageSize();
+    markStack.appendValues(reinterpret_cast<JSValue*>(storage), storageSize);
+}
+
 } // namespace JSC
 
 #endif // JSObject_h
 } // namespace JSC
 
 #endif // JSObject_h
index 8c7b53d5319bb0d4e6d05d71f66d3240308d015a..a5d4da01b67ca4984802b02c42613459ac1e1c74 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "config.h"
 #include "JSPropertyNameIterator.h"
 
 #include "config.h"
 #include "JSPropertyNameIterator.h"
 
+#include "JSGlobalObject.h"
+
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
 
-JSPropertyNameIterator::~JSPropertyNameIterator()
+inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
+    : JSCell(exec->globalData().propertyNameIteratorStructure.get())
+    , m_cachedStructure(0)
+    , m_numCacheableSlots(numCacheableSlots)
+    , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
+    , m_jsStrings(new JSValue[m_jsStringsSize])
 {
 {
+    PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector();
+    for (size_t i = 0; i < m_jsStringsSize; ++i)
+        m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring());
 }
 
 }
 
-JSValue JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const
+JSPropertyNameIterator::~JSPropertyNameIterator()
 {
 {
-    ASSERT_NOT_REACHED();
-    return JSValue();
+    if (m_cachedStructure)
+        m_cachedStructure->clearEnumerationCache(this);
 }
 
 }
 
-bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValue&)
+JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o)
 {
 {
-    ASSERT_NOT_REACHED();
-    return false;
-}
+    ASSERT(!o->structure()->enumerationCache() ||
+            o->structure()->enumerationCache()->cachedStructure() != o->structure() ||
+            o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec));
 
 
-bool JSPropertyNameIterator::toBoolean(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return false;
-}
+    PropertyNameArray propertyNames(exec);
+    o->getPropertyNames(exec, propertyNames);
+    size_t numCacheableSlots = 0;
+    if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasAnonymousSlots() &&
+        !o->structure()->hasGetterSetterProperties() && !o->structure()->isUncacheableDictionary() &&
+        !o->structure()->typeInfo().overridesGetPropertyNames())
+        numCacheableSlots = o->structure()->propertyStorageSize();
 
 
-double JSPropertyNameIterator::toNumber(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return 0;
-}
+    JSPropertyNameIterator* jsPropertyNameIterator = new (exec) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots);
 
 
-UString JSPropertyNameIterator::toString(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return "";
-}
+    if (o->structure()->isDictionary())
+        return jsPropertyNameIterator;
 
 
-JSObject* JSPropertyNameIterator::toObject(ExecState*) const
-{
-    ASSERT_NOT_REACHED();
-    return 0;
+    if (o->structure()->typeInfo().overridesGetPropertyNames())
+        return jsPropertyNameIterator;
+    
+    size_t count = normalizePrototypeChain(exec, o);
+    StructureChain* structureChain = o->structure()->prototypeChain(exec);
+    RefPtr<Structure>* structure = structureChain->head();
+    for (size_t i = 0; i < count; ++i) {
+        if (structure[i]->typeInfo().overridesGetPropertyNames())
+            return jsPropertyNameIterator;
+    }
+
+    jsPropertyNameIterator->setCachedPrototypeChain(structureChain);
+    jsPropertyNameIterator->setCachedStructure(o->structure());
+    o->structure()->setEnumerationCache(jsPropertyNameIterator);
+    return jsPropertyNameIterator;
 }
 
 }
 
-void JSPropertyNameIterator::mark()
+JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
 {
 {
-    JSCell::mark();
-    if (m_object && !m_object->marked())
-        m_object->mark();
+    JSValue& identifier = m_jsStrings[i];
+    if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec))
+        return identifier;
+
+    if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value(exec))))
+        return JSValue();
+    return identifier;
 }
 
 }
 
-void JSPropertyNameIterator::invalidate()
+void JSPropertyNameIterator::markChildren(MarkStack& markStack)
 {
 {
-    ASSERT(m_position == m_end);
-    m_object = 0;
-    m_data.clear();
+    markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 9817c075792008e518092f71960d206ece99c224..3f533a0bf0b7b4cd64649bee9994f5549969a0c1 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,6 +31,7 @@
 
 #include "JSObject.h"
 #include "JSString.h"
 
 #include "JSObject.h"
 #include "JSString.h"
+#include "Operations.h"
 #include "PropertyNameArray.h"
 
 namespace JSC {
 #include "PropertyNameArray.h"
 
 namespace JSC {
@@ -39,77 +40,64 @@ namespace JSC {
     class JSObject;
 
     class JSPropertyNameIterator : public JSCell {
     class JSObject;
 
     class JSPropertyNameIterator : public JSCell {
-    public:
-        static JSPropertyNameIterator* create(ExecState*, JSValue);
+        friend class JIT;
 
 
+    public:
+        static JSPropertyNameIterator* create(ExecState*, JSObject*);
+        
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount);
+        }
+        
         virtual ~JSPropertyNameIterator();
 
         virtual ~JSPropertyNameIterator();
 
-        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
-        virtual bool getPrimitiveNumber(ExecState*, double&, JSValue&);
-        virtual bool toBoolean(ExecState*) const;
-        virtual double toNumber(ExecState*) const;
-        virtual UString toString(ExecState*) const;
-        virtual JSObject* toObject(ExecState*) const;
+        virtual bool isPropertyNameIterator() const { return true; }
+
+        virtual void markChildren(MarkStack&);
+
+        bool getOffset(size_t i, int& offset)
+        {
+            if (i >= m_numCacheableSlots)
+                return false;
+            offset = i;
+            return true;
+        }
+
+        JSValue get(ExecState*, JSObject*, size_t i);
+        size_t size() { return m_jsStringsSize; }
 
 
-        virtual void mark();
+        void setCachedStructure(Structure* structure) { m_cachedStructure = structure; }
+        Structure* cachedStructure() { return m_cachedStructure; }
 
 
-        JSValue next(ExecState*);
-        void invalidate();
+        void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
+        StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
 
     private:
 
     private:
-        JSPropertyNameIterator();
-        JSPropertyNameIterator(JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData);
+        JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
 
 
-        JSObject* m_object;
-        RefPtr<PropertyNameArrayData> m_data;
-        PropertyNameArrayData::const_iterator m_position;
-        PropertyNameArrayData::const_iterator m_end;
+        Structure* m_cachedStructure;
+        RefPtr<StructureChain> m_cachedPrototypeChain;
+        uint32_t m_numCacheableSlots;
+        uint32_t m_jsStringsSize;
+        OwnArrayPtr<JSValue> m_jsStrings;
     };
 
     };
 
-inline JSPropertyNameIterator::JSPropertyNameIterator()
-    : JSCell(0)
-    , m_object(0)
-    , m_position(0)
-    , m_end(0)
-{
-}
-
-inline JSPropertyNameIterator::JSPropertyNameIterator(JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData)
-    : JSCell(0)
-    , m_object(object)
-    , m_data(propertyNameArrayData)
-    , m_position(m_data->begin())
-    , m_end(m_data->end())
-{
-}
-
-inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue v)
-{
-    if (v.isUndefinedOrNull())
-        return new (exec) JSPropertyNameIterator;
-
-    JSObject* o = v.toObject(exec);
-    PropertyNameArray propertyNames(exec);
-    o->getPropertyNames(exec, propertyNames);
-    return new (exec) JSPropertyNameIterator(o, propertyNames.releaseData());
-}
-
-inline JSValue JSPropertyNameIterator::next(ExecState* exec)
-{
-    if (m_position == m_end)
-        return JSValue();
-
-    if (m_data->cachedStructure() == m_object->structure() && m_data->cachedPrototypeChain() == m_object->structure()->prototypeChain(exec))
-        return jsOwnedString(exec, (*m_position++).ustring());
-
-    do {
-        if (m_object->hasProperty(exec, *m_position))
-            return jsOwnedString(exec, (*m_position++).ustring());
-        m_position++;
-    } while (m_position != m_end);
-
-    return JSValue();
-}
+    inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache)
+    {
+        ASSERT(!isDictionary());
+        m_enumerationCache = enumerationCache;
+    }
+
+    inline void Structure::clearEnumerationCache(JSPropertyNameIterator* enumerationCache)
+    {
+        m_enumerationCache.clear(enumerationCache);
+    }
+
+    inline JSPropertyNameIterator* Structure::enumerationCache()
+    {
+        return m_enumerationCache.get();
+    }
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index 85907c825a6598b50d074babedc722746a995bb0..a877ec648c1e45d04c72f38d5f3e26ff578139e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,12 +31,10 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
 
 
 ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
 
-void JSStaticScopeObject::mark()
+void JSStaticScopeObject::markChildren(MarkStack& markStack)
 {
 {
-    JSVariableObject::mark();
-    
-    if (!d()->registerStore.marked())
-        d()->registerStore.mark();
+    JSVariableObject::markChildren(markStack);
+    markStack.append(d()->registerStore.jsValue());
 }
 
 JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
 }
 
 JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
index 2caf540a816e33fea69cc40b3ea70a79826f4694..4d156d4756e3d741578a6da6872771f176ac31b0 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -50,14 +50,17 @@ namespace JSC{
             symbolTable().add(ident.ustring().rep(), SymbolTableEntry(-1, attributes));
         }
         virtual ~JSStaticScopeObject();
             symbolTable().add(ident.ustring().rep(), SymbolTableEntry(-1, attributes));
         }
         virtual ~JSStaticScopeObject();
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
         bool isDynamicScope() const;
         virtual JSObject* toThisObject(ExecState*) const;
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
         void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes);
 
         bool isDynamicScope() const;
         virtual JSObject* toThisObject(ExecState*) const;
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
         void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes);
 
-        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); }
+        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
     private:
         JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); }
 
     private:
         JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); }
index 86f95e0dbd62e1f2c3339adb627b313215d11da6..1e23a15f7565288f202d7a3a2861c80dd7540f16 100644 (file)
 
 #include "JSGlobalObject.h"
 #include "JSObject.h"
 
 #include "JSGlobalObject.h"
 #include "JSObject.h"
+#include "Operations.h"
 #include "StringObject.h"
 #include "StringPrototype.h"
 
 namespace JSC {
 
 #include "StringObject.h"
 #include "StringPrototype.h"
 
 namespace JSC {
 
+void JSString::Rope::destructNonRecursive()
+{
+    Vector<Rope*, 32> workQueue;
+    Rope* rope = this;
+
+    while (true) {
+        unsigned length = rope->ropeLength();
+        for (unsigned i = 0; i < length; ++i) {
+            Fiber& fiber = rope->fibers(i);
+            if (fiber.isString())
+                fiber.string()->deref();
+            else {
+                Rope* nextRope = fiber.rope();
+                if (nextRope->hasOneRef())
+                    workQueue.append(nextRope);
+                else
+                    nextRope->deref();
+            }
+        }
+        if (rope != this)
+            fastFree(rope);
+
+        if (workQueue.isEmpty())
+            return;
+
+        rope = workQueue.last();
+        workQueue.removeLast();
+    }
+}
+
+JSString::Rope::~Rope()
+{
+    destructNonRecursive();
+}
+
+// Overview: this methods converts a JSString from holding a string in rope form
+// down to a simple UString representation.  It does so by building up the string
+// backwards, since we want to avoid recursion, we expect that the tree structure
+// representing the rope is likely imbalanced with more nodes down the left side
+// (since appending to the string is likely more common) - and as such resolving
+// in this fashion should minimize work queue size.  (If we built the queue forwards
+// we would likely have to place all of the constituent UString::Reps into the
+// Vector before performing any concatenation, but by working backwards we likely
+// only fill the queue with the number of substrings at any given level in a
+// rope-of-ropes.)
+void JSString::resolveRope(ExecState* exec) const
+{
+    ASSERT(isRope());
+
+    // Allocate the buffer to hold the final string, position initially points to the end.
+    UChar* buffer;
+    if (PassRefPtr<UStringImpl> newImpl = UStringImpl::tryCreateUninitialized(m_stringLength, buffer))
+        m_value = newImpl;
+    else {
+        for (unsigned i = 0; i < m_ropeLength; ++i) {
+            m_fibers[i].deref();
+            m_fibers[i] = static_cast<void*>(0);
+        }
+        m_ropeLength = 0;
+        ASSERT(!isRope());
+        ASSERT(m_value == UString());
+        throwOutOfMemoryError(exec);
+        return;
+    }
+    UChar* position = buffer + m_stringLength;
+
+    // Start with the current Rope.
+    Vector<Rope::Fiber, 32> workQueue;
+    Rope::Fiber currentFiber;
+    for (unsigned i = 0; i < (m_ropeLength - 1); ++i)
+        workQueue.append(m_fibers[i]);
+    currentFiber = m_fibers[m_ropeLength - 1];
+    while (true) {
+        if (currentFiber.isRope()) {
+            Rope* rope = currentFiber.rope();
+            // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber'
+            // (we will be working backwards over the rope).
+            unsigned ropeLengthMinusOne = rope->ropeLength() - 1;
+            for (unsigned i = 0; i < ropeLengthMinusOne; ++i)
+                workQueue.append(rope->fibers(i));
+            currentFiber = rope->fibers(ropeLengthMinusOne);
+        } else {
+            UString::Rep* string = currentFiber.string();
+            unsigned length = string->size();
+            position -= length;
+            UStringImpl::copyChars(position, string->data(), length);
+
+            // Was this the last item in the work queue?
+            if (workQueue.isEmpty()) {
+                // Create a string from the UChar buffer, clear the rope RefPtr.
+                ASSERT(buffer == position);
+                for (unsigned i = 0; i < m_ropeLength; ++i) {
+                    m_fibers[i].deref();
+                    m_fibers[i] = static_cast<void*>(0);
+                }
+                m_ropeLength = 0;
+
+                ASSERT(!isRope());
+                return;
+            }
+
+            // No! - set the next item up to process.
+            currentFiber = workQueue.last();
+            workQueue.removeLast();
+        }
+    }
+}
+
 JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
 {
     return const_cast<JSString*>(this);
 }
 
 JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
 {
     return const_cast<JSString*>(this);
 }
 
-bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValue& value)
+bool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result)
 {
 {
-    value = this;
-    number = m_value.toDouble();
+    result = this;
+    number = value(exec).toDouble();
     return false;
 }
 
 bool JSString::toBoolean(ExecState*) const
 {
     return false;
 }
 
 bool JSString::toBoolean(ExecState*) const
 {
-    return !m_value.isEmpty();
+    return m_stringLength;
 }
 
 }
 
-double JSString::toNumber(ExecState*) const
+double JSString::toNumber(ExecState* exec) const
 {
 {
-    return m_value.toDouble();
+    return value(exec).toDouble();
 }
 
 }
 
-UString JSString::toString(ExecState*) const
+UString JSString::toString(ExecState* exec) const
 {
 {
-    return m_value;
+    return value(exec);
 }
 
 }
 
-UString JSString::toThisString(ExecState*) const
+UString JSString::toThisString(ExecState* exec) const
 {
 {
-    return m_value;
+    return value(exec);
 }
 
 JSString* JSString::toThisJSString(ExecState*)
 }
 
 JSString* JSString::toThisJSString(ExecState*)
@@ -103,54 +212,40 @@ bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNam
     return true;
 }
 
     return true;
 }
 
-bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    // The semantics here are really getPropertySlot, not getOwnPropertySlot.
-    // This function should only be called by JSValue::get.
-    if (getStringPropertySlot(exec, propertyName, slot))
+    if (propertyName == exec->propertyNames().length) {
+        descriptor.setDescriptor(jsNumber(exec, m_stringLength), DontEnum | DontDelete | ReadOnly);
         return true;
         return true;
-    return JSString::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
-}
-
-JSString* jsString(JSGlobalData* globalData, const UString& s)
-{
-    int size = s.size();
-    if (!size)
-        return globalData->smallStrings.emptyString(globalData);
-    if (size == 1) {
-        UChar c = s.data()[0];
-        if (c <= 0xFF)
-            return globalData->smallStrings.singleCharacterString(globalData, c);
     }
     }
-    return new (globalData) JSString(globalData, s);
-}
     
     
-JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
-{
-    ASSERT(offset <= static_cast<unsigned>(s.size()));
-    ASSERT(length <= static_cast<unsigned>(s.size()));
-    ASSERT(offset + length <= static_cast<unsigned>(s.size()));
-    if (!length)
-        return globalData->smallStrings.emptyString(globalData);
-    if (length == 1) {
-        UChar c = s.data()[offset];
-        if (c <= 0xFF)
-            return globalData->smallStrings.singleCharacterString(globalData, c);
+    bool isStrictUInt32;
+    unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
+    if (isStrictUInt32 && i < m_stringLength) {
+        descriptor.setDescriptor(jsSingleCharacterSubstring(exec, value(exec), i), DontDelete | ReadOnly);
+        return true;
     }
     }
-    return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, length));
+    
+    return false;
 }
 
 }
 
-JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
+bool JSString::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    int size = s.size();
-    if (!size)
-        return globalData->smallStrings.emptyString(globalData);
-    if (size == 1) {
-        UChar c = s.data()[0];
-        if (c <= 0xFF)
-            return globalData->smallStrings.singleCharacterString(globalData, c);
-    }
-    return new (globalData) JSString(globalData, s, JSString::HasOtherOwner);
+    if (getStringPropertyDescriptor(exec, propertyName, descriptor))
+        return true;
+    if (propertyName != exec->propertyNames().underscoreProto)
+        return false;
+    descriptor.setDescriptor(exec->lexicalGlobalObject()->stringPrototype(), DontEnum);
+    return true;
+}
+
+bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+    // The semantics here are really getPropertySlot, not getOwnPropertySlot.
+    // This function should only be called by JSValue::get.
+    if (getStringPropertySlot(exec, propertyName, slot))
+        return true;
+    return JSString::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index ade3c3b9968055f3dfdb75605f1604eef2dd3bf8..af03025170e0e743bd4e1f671736eab4119362bf 100644 (file)
@@ -27,6 +27,7 @@
 #include "CommonIdentifiers.h"
 #include "Identifier.h"
 #include "JSNumberCell.h"
 #include "CommonIdentifiers.h"
 #include "Identifier.h"
 #include "JSNumberCell.h"
+#include "PropertyDescriptor.h"
 #include "PropertySlot.h"
 
 namespace JSC {
 #include "PropertySlot.h"
 
 namespace JSC {
@@ -58,14 +59,117 @@ namespace JSC {
     JSString* jsOwnedString(JSGlobalData*, const UString&); 
     JSString* jsOwnedString(ExecState*, const UString&); 
 
     JSString* jsOwnedString(JSGlobalData*, const UString&); 
     JSString* jsOwnedString(ExecState*, const UString&); 
 
-    class JSString : public JSCell {
-        friend class JIT;
-        friend class VPtrSet;
+    typedef void (*JSStringFinalizerCallback)(JSString*, void* context);
+    JSString* jsStringWithFinalizer(ExecState*, const UString&, JSStringFinalizerCallback callback, void* context);
 
 
+    class JS_EXPORTCLASS JSString : public JSCell {
     public:
     public:
-        JSString(JSGlobalData* globalData, const UString& value)
+        friend class JIT;
+        friend class JSGlobalData;
+
+        // A Rope is a string composed of a set of substrings.
+        class Rope : public RefCounted<Rope> {
+        public:
+            // A Rope is composed from a set of smaller strings called Fibers.
+            // Each Fiber in a rope is either UString::Rep or another Rope.
+            class Fiber {
+            public:
+                Fiber() : m_value(0) {}
+                Fiber(UString::Rep* string) : m_value(reinterpret_cast<intptr_t>(string)) {}
+                Fiber(Rope* rope) : m_value(reinterpret_cast<intptr_t>(rope) | 1) {}
+
+                Fiber(void* nonFiber) : m_value(reinterpret_cast<intptr_t>(nonFiber)) {}
+
+                void deref()
+                {
+                    if (isRope())
+                        rope()->deref();
+                    else
+                        string()->deref();
+                }
+
+                Fiber& ref()
+                {
+                    if (isString())
+                        string()->ref();
+                    else
+                        rope()->ref();
+                    return *this;
+                }
+
+                unsigned refAndGetLength()
+                {
+                    if (isString()) {
+                        UString::Rep* rep = string();
+                        return rep->ref()->size();
+                    } else {
+                        Rope* r = rope();
+                        r->ref();
+                        return r->stringLength();
+                    }
+                }
+
+                bool isRope() { return m_value & 1; }
+                Rope* rope() { return reinterpret_cast<Rope*>(m_value & ~1); }
+                bool isString() { return !isRope(); }
+                UString::Rep* string() { return reinterpret_cast<UString::Rep*>(m_value); }
+
+                void* nonFiber() { return reinterpret_cast<void*>(m_value); }
+            private:
+                intptr_t m_value;
+            };
+
+            // Creates a Rope comprising of 'ropeLength' Fibers.
+            // The Rope is constructed in an uninitialized state - initialize must be called for each Fiber in the Rope.
+            static PassRefPtr<Rope> createOrNull(unsigned ropeLength)
+            {
+                void* allocation;
+                if (tryFastMalloc(sizeof(Rope) + (ropeLength - 1) * sizeof(Fiber)).getValue(allocation))
+                    return adoptRef(new (allocation) Rope(ropeLength));
+                return 0;
+            }
+
+            ~Rope();
+            void destructNonRecursive();
+
+            void append(unsigned &index, Fiber& fiber)
+            {
+                m_fibers[index++] = fiber;
+                m_stringLength += fiber.refAndGetLength();
+            }
+            void append(unsigned &index, const UString& string)
+            {
+                UString::Rep* rep = string.rep();
+                m_fibers[index++] = Fiber(rep);
+                m_stringLength += rep->ref()->size();
+            }
+            void append(unsigned& index, JSString* jsString)
+            {
+                if (jsString->isRope()) {
+                    for (unsigned i = 0; i < jsString->m_ropeLength; ++i)
+                        append(index, jsString->m_fibers[i]);
+                } else
+                    append(index, jsString->string());
+            }
+
+            unsigned ropeLength() { return m_ropeLength; }
+            unsigned stringLength() { return m_stringLength; }
+            Fiber& fibers(unsigned index) { return m_fibers[index]; }
+
+        private:
+            Rope(unsigned ropeLength) : m_ropeLength(ropeLength), m_stringLength(0) {}
+            void* operator new(size_t, void* inPlace) { return inPlace; }
+            
+            unsigned m_ropeLength;
+            unsigned m_stringLength;
+            Fiber m_fibers[1];
+        };
+
+        ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value)
             : JSCell(globalData->stringStructure.get())
             : JSCell(globalData->stringStructure.get())
+            , m_stringLength(value.size())
             , m_value(value)
             , m_value(value)
+            , m_ropeLength(0)
         {
             Heap::heap(this)->reportExtraMemoryCost(value.cost());
         }
         {
             Heap::heap(this)->reportExtraMemoryCost(value.cost());
         }
@@ -73,30 +177,164 @@ namespace JSC {
         enum HasOtherOwnerType { HasOtherOwner };
         JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
             : JSCell(globalData->stringStructure.get())
         enum HasOtherOwnerType { HasOtherOwner };
         JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
             : JSCell(globalData->stringStructure.get())
+            , m_stringLength(value.size())
             , m_value(value)
             , m_value(value)
+            , m_ropeLength(0)
         {
         }
         JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType)
             : JSCell(globalData->stringStructure.get())
         {
         }
         JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType)
             : JSCell(globalData->stringStructure.get())
+            , m_stringLength(value->size())
             , m_value(value)
             , m_value(value)
+            , m_ropeLength(0)
         {
         }
         {
         }
-        
-        const UString& value() const { return m_value; }
+        JSString(JSGlobalData* globalData, PassRefPtr<JSString::Rope> rope)
+            : JSCell(globalData->stringStructure.get())
+            , m_stringLength(rope->stringLength())
+            , m_ropeLength(1)
+        {
+            m_fibers[0] = rope.releaseRef();
+        }
+        // This constructor constructs a new string by concatenating s1 & s2.
+        // This should only be called with ropeLength <= 3.
+        JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, JSString* s2)
+            : JSCell(globalData->stringStructure.get())
+            , m_stringLength(s1->length() + s2->length())
+            , m_ropeLength(ropeLength)
+        {
+            ASSERT(ropeLength <= s_maxInternalRopeLength);
+            unsigned index = 0;
+            appendStringInConstruct(index, s1);
+            appendStringInConstruct(index, s2);
+            ASSERT(ropeLength == index);
+        }
+        // This constructor constructs a new string by concatenating s1 & s2.
+        // This should only be called with ropeLength <= 3.
+        JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, const UString& u2)
+            : JSCell(globalData->stringStructure.get())
+            , m_stringLength(s1->length() + u2.size())
+            , m_ropeLength(ropeLength)
+        {
+            ASSERT(ropeLength <= s_maxInternalRopeLength);
+            unsigned index = 0;
+            appendStringInConstruct(index, s1);
+            appendStringInConstruct(index, u2);
+            ASSERT(ropeLength == index);
+        }
+        // This constructor constructs a new string by concatenating s1 & s2.
+        // This should only be called with ropeLength <= 3.
+        JSString(JSGlobalData* globalData, unsigned ropeLength, const UString& u1, JSString* s2)
+            : JSCell(globalData->stringStructure.get())
+            , m_stringLength(u1.size() + s2->length())
+            , m_ropeLength(ropeLength)
+        {
+            ASSERT(ropeLength <= s_maxInternalRopeLength);
+            unsigned index = 0;
+            appendStringInConstruct(index, u1);
+            appendStringInConstruct(index, s2);
+            ASSERT(ropeLength == index);
+        }
+        // This constructor constructs a new string by concatenating v1, v2 & v3.
+        // This should only be called with ropeLength <= 3 ... which since every
+        // value must require a ropeLength of at least one implies that the length
+        // for each value must be exactly 1!
+        JSString(ExecState* exec, JSValue v1, JSValue v2, JSValue v3)
+            : JSCell(exec->globalData().stringStructure.get())
+            , m_stringLength(0)
+            , m_ropeLength(s_maxInternalRopeLength)
+        {
+            unsigned index = 0;
+            appendValueInConstructAndIncrementLength(exec, index, v1);
+            appendValueInConstructAndIncrementLength(exec, index, v2);
+            appendValueInConstructAndIncrementLength(exec, index, v3);
+            ASSERT(index == s_maxInternalRopeLength);
+        }
+
+        JSString(JSGlobalData* globalData, const UString& value, JSStringFinalizerCallback finalizer, void* context)
+            : JSCell(globalData->stringStructure.get())
+            , m_stringLength(value.size())
+            , m_value(value)
+            , m_ropeLength(0)
+        {
+            // nasty hack because we can't union non-POD types
+            m_fibers[0] = reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(finalizer));
+            m_fibers[1] = context;
+            Heap::heap(this)->reportExtraMemoryCost(value.cost());
+        }
+
+        ~JSString()
+        {
+            ASSERT(vptr() == JSGlobalData::jsStringVPtr);
+            for (unsigned i = 0; i < m_ropeLength; ++i)
+                m_fibers[i].deref();
+
+            if (!m_ropeLength && m_fibers[0].nonFiber()) {
+                JSStringFinalizerCallback finalizer = reinterpret_cast<JSStringFinalizerCallback>(m_fibers[0].nonFiber());
+                finalizer(this, m_fibers[1].nonFiber());
+            }
+        }
+
+        const UString& value(ExecState* exec) const
+        {
+            if (isRope())
+                resolveRope(exec);
+            return m_value;
+        }
+        const UString tryGetValue() const
+        {
+            if (isRope())
+                UString();
+            return m_value;
+        }
+        unsigned length() { return m_stringLength; }
 
         bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
 
         bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+        bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
 
 
-        bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); }
-        JSString* getIndex(JSGlobalData*, unsigned);
+        bool canGetIndex(unsigned i) { return i < m_stringLength; }
+        JSString* getIndex(ExecState*, unsigned);
 
 
-        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion)); }
+        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount); }
 
     private:
         enum VPtrStealingHackType { VPtrStealingHack };
         JSString(VPtrStealingHackType) 
             : JSCell(0)
 
     private:
         enum VPtrStealingHackType { VPtrStealingHack };
         JSString(VPtrStealingHackType) 
             : JSCell(0)
+            , m_ropeLength(0)
+        {
+        }
+
+        void resolveRope(ExecState*) const;
+
+        void appendStringInConstruct(unsigned& index, const UString& string)
+        {
+            m_fibers[index++] = Rope::Fiber(string.rep()->ref());
+        }
+
+        void appendStringInConstruct(unsigned& index, JSString* jsString)
+        {
+            if (jsString->isRope()) {
+                for (unsigned i = 0; i < jsString->m_ropeLength; ++i)
+                    m_fibers[index++] = jsString->m_fibers[i].ref();
+            } else
+                appendStringInConstruct(index, jsString->string());
+        }
+
+        void appendValueInConstructAndIncrementLength(ExecState* exec, unsigned& index, JSValue v)
         {
         {
+            if (v.isString()) {
+                ASSERT(asCell(v)->isString());
+                JSString* s = static_cast<JSString*>(asCell(v));
+                ASSERT(s->ropeLength() == 1);
+                appendStringInConstruct(index, s);
+                m_stringLength += s->length();
+            } else {
+                UString u(v.toString(exec));
+                m_fibers[index++] = Rope::Fiber(u.rep()->ref());
+                m_stringLength += u.size();
+            }
         }
 
         virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
         }
 
         virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
@@ -113,12 +351,40 @@ namespace JSC {
         // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
         // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
-
-        UString m_value;
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+
+        static const unsigned s_maxInternalRopeLength = 3;
+
+        // A string is represented either by a UString or a Rope.
+        unsigned m_stringLength;
+        mutable UString m_value;
+        mutable unsigned m_ropeLength;
+        mutable Rope::Fiber m_fibers[s_maxInternalRopeLength];
+
+        bool isRope() const { return m_ropeLength; }
+        UString& string() { ASSERT(!isRope()); return m_value; }
+        unsigned ropeLength() { return m_ropeLength ? m_ropeLength : 1; }
+
+        friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2);
+        friend JSValue jsString(ExecState* exec, const UString& u1, JSString* s2);
+        friend JSValue jsString(ExecState* exec, JSString* s1, const UString& u2);
+        friend JSValue jsString(ExecState* exec, Register* strings, unsigned count);
+        friend JSValue jsString(ExecState* exec, JSValue thisValue, const ArgList& args);
+        friend JSString* jsStringWithFinalizer(ExecState*, const UString&, JSStringFinalizerCallback callback, void* context);
     };
 
     JSString* asString(JSValue);
 
     };
 
     JSString* asString(JSValue);
 
+    // When an object is created from a different DLL, MSVC changes vptr to a "local" one right after invoking a constructor,
+    // see <http://groups.google.com/group/microsoft.public.vc.language/msg/55cdcefeaf770212>.
+    // This breaks isJSString(), and we don't need that hack anyway, so we change vptr back to primary one.
+    // The below function must be called by any inline function that invokes a JSString constructor.
+#if COMPILER(MSVC) && !defined(BUILDING_JavaScriptCore)
+    inline JSString* fixupVPtr(JSGlobalData* globalData, JSString* string) { string->setVPtr(globalData->jsStringVPtr); return string; }
+#else
+    inline JSString* fixupVPtr(JSGlobalData*, JSString* string) { return string; }
+#endif
+
     inline JSString* asString(JSValue value)
     {
         ASSERT(asCell(value)->isString());
     inline JSString* asString(JSValue value)
     {
         ASSERT(asCell(value)->isString());
@@ -134,7 +400,7 @@ namespace JSC {
     {
         if (c <= 0xFF)
             return globalData->smallStrings.singleCharacterString(globalData, c);
     {
         if (c <= 0xFF)
             return globalData->smallStrings.singleCharacterString(globalData, c);
-        return new (globalData) JSString(globalData, UString(&c, 1));
+        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(&c, 1)));
     }
 
     inline JSString* jsSingleCharacterSubstring(JSGlobalData* globalData, const UString& s, unsigned offset)
     }
 
     inline JSString* jsSingleCharacterSubstring(JSGlobalData* globalData, const UString& s, unsigned offset)
@@ -143,7 +409,7 @@ namespace JSC {
         UChar c = s.data()[offset];
         if (c <= 0xFF)
             return globalData->smallStrings.singleCharacterString(globalData, c);
         UChar c = s.data()[offset];
         if (c <= 0xFF)
             return globalData->smallStrings.singleCharacterString(globalData, c);
-        return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, 1));
+        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, 1))));
     }
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
     }
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
@@ -151,19 +417,67 @@ namespace JSC {
         ASSERT(s);
         ASSERT(s[0]);
         ASSERT(s[1]);
         ASSERT(s);
         ASSERT(s[0]);
         ASSERT(s[1]);
-        return new (globalData) JSString(globalData, s);
+        return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
     }
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
     {
         ASSERT(s.size() > 1);
     }
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
     {
         ASSERT(s.size() > 1);
-        return new (globalData) JSString(globalData, s);
+        return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
     }
 
     }
 
-    inline JSString* JSString::getIndex(JSGlobalData* globalData, unsigned i)
+    inline JSString* JSString::getIndex(ExecState* exec, unsigned i)
     {
         ASSERT(canGetIndex(i));
     {
         ASSERT(canGetIndex(i));
-        return jsSingleCharacterSubstring(globalData, m_value, i);
+        return jsSingleCharacterSubstring(&exec->globalData(), value(exec), i);
+    }
+
+    inline JSString* jsString(JSGlobalData* globalData, const UString& s)
+    {
+        int size = s.size();
+        if (!size)
+            return globalData->smallStrings.emptyString(globalData);
+        if (size == 1) {
+            UChar c = s.data()[0];
+            if (c <= 0xFF)
+                return globalData->smallStrings.singleCharacterString(globalData, c);
+        }
+        return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
+    }
+
+    inline JSString* jsStringWithFinalizer(ExecState* exec, const UString& s, JSStringFinalizerCallback callback, void* context)
+    {
+        ASSERT(s.size() && (s.size() > 1 || s.data()[0] > 0xFF));
+        JSGlobalData* globalData = &exec->globalData();
+        return fixupVPtr(globalData, new (globalData) JSString(globalData, s, callback, context));
+    }
+
+    inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
+    {
+        ASSERT(offset <= static_cast<unsigned>(s.size()));
+        ASSERT(length <= static_cast<unsigned>(s.size()));
+        ASSERT(offset + length <= static_cast<unsigned>(s.size()));
+        if (!length)
+            return globalData->smallStrings.emptyString(globalData);
+        if (length == 1) {
+            UChar c = s.data()[offset];
+            if (c <= 0xFF)
+                return globalData->smallStrings.singleCharacterString(globalData, c);
+        }
+        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, length)), JSString::HasOtherOwner));
+    }
+
+    inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
+    {
+        int size = s.size();
+        if (!size)
+            return globalData->smallStrings.emptyString(globalData);
+        if (size == 1) {
+            UChar c = s.data()[0];
+            if (c <= 0xFF)
+                return globalData->smallStrings.singleCharacterString(globalData, c);
+        }
+        return fixupVPtr(globalData, new (globalData) JSString(globalData, s, JSString::HasOtherOwner));
     }
 
     inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
     }
 
     inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
@@ -178,14 +492,14 @@ namespace JSC {
     ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
     {
         if (propertyName == exec->propertyNames().length) {
     ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
     {
         if (propertyName == exec->propertyNames().length) {
-            slot.setValue(jsNumber(exec, m_value.size()));
+            slot.setValue(jsNumber(exec, m_stringLength));
             return true;
         }
 
         bool isStrictUInt32;
         unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
             return true;
         }
 
         bool isStrictUInt32;
         unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
-        if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) {
-            slot.setValue(jsSingleCharacterSubstring(exec, m_value, i));
+        if (isStrictUInt32 && i < m_stringLength) {
+            slot.setValue(jsSingleCharacterSubstring(exec, value(exec), i));
             return true;
         }
 
             return true;
         }
 
@@ -194,8 +508,8 @@ namespace JSC {
         
     ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
     {
         
     ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
     {
-        if (propertyName < static_cast<unsigned>(m_value.size())) {
-            slot.setValue(jsSingleCharacterSubstring(exec, m_value, propertyName));
+        if (propertyName < m_stringLength) {
+            slot.setValue(jsSingleCharacterSubstring(exec, value(exec), propertyName));
             return true;
         }
 
             return true;
         }
 
@@ -211,6 +525,46 @@ namespace JSC {
         return isCell() ? asCell()->toThisJSString(exec) : jsString(exec, toString(exec));
     }
 
         return isCell() ? asCell()->toThisJSString(exec) : jsString(exec, toString(exec));
     }
 
+    inline UString JSValue::toString(ExecState* exec) const
+    {
+        if (isString())
+            return static_cast<JSString*>(asCell())->value(exec);
+        if (isInt32())
+            return exec->globalData().numericStrings.add(asInt32());
+        if (isDouble())
+            return exec->globalData().numericStrings.add(asDouble());
+        if (isTrue())
+            return "true";
+        if (isFalse())
+            return "false";
+        if (isNull())
+            return "null";
+        if (isUndefined())
+            return "undefined";
+        ASSERT(isCell());
+        return asCell()->toString(exec);
+    }
+
+    inline UString JSValue::toPrimitiveString(ExecState* exec) const
+    {
+        if (isString())
+            return static_cast<JSString*>(asCell())->value(exec);
+        if (isInt32())
+            return exec->globalData().numericStrings.add(asInt32());
+        if (isDouble())
+            return exec->globalData().numericStrings.add(asDouble());
+        if (isTrue())
+            return "true";
+        if (isFalse())
+            return "false";
+        if (isNull())
+            return "null";
+        if (isUndefined())
+            return "undefined";
+        ASSERT(isCell());
+        return asCell()->toPrimitive(exec, NoPreference).toString(exec);
+    }
+
 } // namespace JSC
 
 #endif // JSString_h
 } // namespace JSC
 
 #endif // JSString_h
index 68f289039ce74f095aa58f9fdb18af134be89627..882b2188e97b886eb484437dc4cdefc35f9ab192 100644 (file)
@@ -33,8 +33,10 @@ namespace JSC {
         NumberType        = 3,
         NullType          = 4,
         StringType        = 5,
         NumberType        = 3,
         NullType          = 4,
         StringType        = 5,
-        ObjectType        = 6,
-        GetterSetterType  = 7
+        // The CompoundType value must come before any JSType that may have children
+        CompoundType      = 6,
+        ObjectType        = 7,
+        GetterSetterType  = 8
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
diff --git a/runtime/JSTypeInfo.h b/runtime/JSTypeInfo.h
new file mode 100644 (file)
index 0000000..7c89600
--- /dev/null
@@ -0,0 +1,78 @@
+// -*- 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 JSTypeInfo_h
+#define JSTypeInfo_h
+
+// This file would be called TypeInfo.h, but that conflicts with <typeinfo.h>
+// in the STL on systems without case-sensitive file systems. 
+
+#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 ImplementsDefaultHasInstance = 1 << 3;
+    static const unsigned NeedsThisConversion = 1 << 4;
+    static const unsigned OverridesGetOwnPropertySlot = 1 << 5;
+    static const unsigned OverridesMarkChildren = 1 << 6;
+    static const unsigned OverridesGetPropertyNames = 1 << 7;
+
+    class TypeInfo {
+        friend class JIT;
+    public:
+        TypeInfo(JSType type, unsigned flags = 0)
+            : m_type(type)
+        {
+            // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance)
+            if ((flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
+                m_flags = flags | ImplementsDefaultHasInstance;
+            else
+                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 overridesGetOwnPropertySlot() const { return m_flags & OverridesGetOwnPropertySlot; }
+        bool overridesMarkChildren() const { return m_flags & OverridesMarkChildren; }
+        bool overridesGetPropertyNames() const { return m_flags & OverridesGetPropertyNames; }
+        unsigned flags() const { return m_flags; }
+
+    private:
+        JSType m_type;
+        unsigned m_flags;
+    };
+
+}
+
+#endif // JSTypeInfo_h
index 39a4093d46b637ecd437774488f694705c5e3bba..699c1cd7ccf79dbdea66ec293ec2b8521d7bb10c 100644 (file)
@@ -110,7 +110,10 @@ char* JSValue::description()
 {
     static const size_t size = 32;
     static char description[size];
 {
     static const size_t size = 32;
     static char description[size];
-    if (isInt32())
+
+    if (!*this)
+        snprintf(description, size, "<JSValue()>");
+    else if (isInt32())
         snprintf(description, size, "Int32: %d", asInt32());
     else if (isDouble())
         snprintf(description, size, "Double: %lf", asDouble());
         snprintf(description, size, "Int32: %d", asInt32());
     else if (isDouble())
         snprintf(description, size, "Double: %lf", asDouble());
index cbf8fc54880da6f344fe762094737bf56f09b4f2..6da921f307cba69ff9babb7b862c461a3e516034 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  */
 
  *
  */
 
-#include <stddef.h> // for size_t
-#include <stdint.h>
-
 #ifndef JSValue_h
 #define JSValue_h
 
 #include "CallData.h"
 #include "ConstructData.h"
 #include <math.h>
 #ifndef JSValue_h
 #define JSValue_h
 
 #include "CallData.h"
 #include "ConstructData.h"
 #include <math.h>
+#include <stddef.h> // for size_t
+#include <stdint.h>
 #include <wtf/AlwaysInline.h>
 #include <wtf/Assertions.h>
 #include <wtf/HashTraits.h>
 #include <wtf/AlwaysInline.h>
 #include <wtf/Assertions.h>
 #include <wtf/HashTraits.h>
@@ -81,6 +80,7 @@ namespace JSC {
         enum JSUndefinedTag { JSUndefined };
         enum JSTrueTag { JSTrue };
         enum JSFalseTag { JSFalse };
         enum JSUndefinedTag { JSUndefined };
         enum JSTrueTag { JSTrue };
         enum JSFalseTag { JSFalse };
+        enum EncodeAsDoubleTag { EncodeAsDouble };
 
         JSValue();
         JSValue(JSNullTag);
 
         JSValue();
         JSValue(JSNullTag);
@@ -91,6 +91,7 @@ namespace JSC {
         JSValue(const JSCell* ptr);
 
         // Numbers
         JSValue(const JSCell* ptr);
 
         // Numbers
+        JSValue(EncodeAsDoubleTag, ExecState*, double);
         JSValue(ExecState*, double);
         JSValue(ExecState*, char);
         JSValue(ExecState*, unsigned char);
         JSValue(ExecState*, double);
         JSValue(ExecState*, char);
         JSValue(ExecState*, unsigned char);
@@ -129,15 +130,15 @@ namespace JSC {
         bool isString() const;
         bool isGetterSetter() const;
         bool isObject() const;
         bool isString() const;
         bool isGetterSetter() const;
         bool isObject() const;
-        bool isObject(const ClassInfo*) const;
+        bool inherits(const ClassInfo*) const;
         
         // Extracting the value.
         bool getBoolean(bool&) const;
         bool getBoolean() const; // false if not a boolean
         bool getNumber(double&) const;
         double uncheckedGetNumber() const;
         
         // Extracting the value.
         bool getBoolean(bool&) const;
         bool getBoolean() const; // false if not a boolean
         bool getNumber(double&) const;
         double uncheckedGetNumber() const;
-        bool getString(UString&) const;
-        UString getString() const; // null string if not a string
+        bool getString(ExecState* exec, UString&) const;
+        UString getString(ExecState* exec) const; // null string if not a string
         JSObject* getObject() const; // 0 if not an object
 
         CallType getCallData(CallData&);
         JSObject* getObject() const; // 0 if not an object
 
         CallType getCallData(CallData&);
@@ -157,6 +158,7 @@ namespace JSC {
         double toNumber(ExecState*) const;
         JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
         UString toString(ExecState*) const;
         double toNumber(ExecState*) const;
         JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
         UString toString(ExecState*) const;
+        UString toPrimitiveString(ExecState*) const;
         JSObject* toObject(ExecState*) const;
 
         // Integer conversions.
         JSObject* toObject(ExecState*) const;
 
         // Integer conversions.
@@ -167,14 +169,14 @@ namespace JSC {
         uint32_t toUInt32(ExecState*) const;
         uint32_t toUInt32(ExecState*, bool& ok) const;
 
         uint32_t toUInt32(ExecState*) const;
         uint32_t toUInt32(ExecState*, bool& ok) const;
 
+#if ENABLE(JSC_ZOMBIES)
+        bool isZombie() const;
+#endif
+
         // Floating point conversions (this is a convenience method for webcore;
         // signle precision float is not a representation used in JS or JSC).
         float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
 
         // Floating point conversions (this is a convenience method for webcore;
         // signle precision float is not a representation used in JS or JSC).
         float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
 
-        // Garbage collection.
-        void mark();
-        bool marked() const;
-
         // Object operations, with the toObject operation included.
         JSValue get(ExecState*, const Identifier& propertyName) const;
         JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
         // Object operations, with the toObject operation included.
         JSValue get(ExecState*, const Identifier& propertyName) const;
         JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
@@ -191,9 +193,9 @@ namespace JSC {
         static bool equal(ExecState* exec, JSValue v1, JSValue v2);
         static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
         static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
         static bool equal(ExecState* exec, JSValue v1, JSValue v2);
         static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
         static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
-        static bool strictEqual(JSValue v1, JSValue v2);
-        static bool strictEqualSlowCase(JSValue v1, JSValue v2);
-        static bool strictEqualSlowCaseInline(JSValue v1, JSValue v2);
+        static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2);
+        static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2);
+        static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
 
         JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object
 
 
         JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object
 
@@ -218,7 +220,8 @@ namespace JSC {
         enum { FalseTag =        0xfffffffc };
         enum { NullTag =         0xfffffffb };
         enum { UndefinedTag =    0xfffffffa };
         enum { FalseTag =        0xfffffffc };
         enum { NullTag =         0xfffffffb };
         enum { UndefinedTag =    0xfffffffa };
-        enum { DeletedValueTag = 0xfffffff9 };
+        enum { EmptyValueTag =   0xfffffff9 };
+        enum { DeletedValueTag = 0xfffffff8 };
 
         enum { LowestTag =  DeletedValueTag };
 
 
         enum { LowestTag =  DeletedValueTag };
 
@@ -232,7 +235,7 @@ namespace JSC {
         union {
             EncodedJSValue asEncodedJSValue;
             double asDouble;
         union {
             EncodedJSValue asEncodedJSValue;
             double asDouble;
-#if PLATFORM(BIG_ENDIAN)
+#if CPU(BIG_ENDIAN)
             struct {
                 int32_t tag;
                 int32_t payload;
             struct {
                 int32_t tag;
                 int32_t payload;
@@ -283,6 +286,11 @@ namespace JSC {
         return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
     }
 
         return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
     }
 
+    ALWAYS_INLINE JSValue jsDoubleNumber(ExecState* exec, double d)
+    {
+        return JSValue(JSValue::EncodeAsDouble, exec, d);
+    }
+
     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d)
     {
         return JSValue(exec, d);
     ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d)
     {
         return JSValue(exec, d);
@@ -377,6 +385,14 @@ namespace JSC {
         return static_cast<uint32_t>(val);
     }
 
         return static_cast<uint32_t>(val);
     }
 
+    // FIXME: We should deprecate this and just use JSValue::asCell() instead.
+    JSCell* asCell(JSValue);
+
+    inline JSCell* asCell(JSValue value)
+    {
+        return value.asCell();
+    }
+
     ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
     {
         if (isInt32())
     ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
     {
         if (isInt32())
@@ -427,12 +443,15 @@ namespace JSC {
     {
         JSValue v;
         v.u.asEncodedJSValue = encodedJSValue;
     {
         JSValue v;
         v.u.asEncodedJSValue = encodedJSValue;
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!v.isZombie());
+#endif
         return v;
     }
 
     inline JSValue::JSValue()
     {
         return v;
     }
 
     inline JSValue::JSValue()
     {
-        u.asBits.tag = CellTag;
+        u.asBits.tag = EmptyValueTag;
         u.asBits.payload = 0;
     }
 
         u.asBits.payload = 0;
     }
 
@@ -468,19 +487,32 @@ namespace JSC {
 
     inline JSValue::JSValue(JSCell* ptr)
     {
 
     inline JSValue::JSValue(JSCell* ptr)
     {
-        u.asBits.tag = CellTag;
+        if (ptr)
+            u.asBits.tag = CellTag;
+        else
+            u.asBits.tag = EmptyValueTag;
         u.asBits.payload = reinterpret_cast<int32_t>(ptr);
         u.asBits.payload = reinterpret_cast<int32_t>(ptr);
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie());
+#endif
     }
 
     inline JSValue::JSValue(const JSCell* ptr)
     {
     }
 
     inline JSValue::JSValue(const JSCell* ptr)
     {
-        u.asBits.tag = CellTag;
+        if (ptr)
+            u.asBits.tag = CellTag;
+        else
+            u.asBits.tag = EmptyValueTag;
         u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
         u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie());
+#endif
     }
 
     inline JSValue::operator bool() const
     {
     }
 
     inline JSValue::operator bool() const
     {
-        return u.asBits.payload || tag() != CellTag;
+        ASSERT(tag() != DeletedValueTag);
+        return tag() != EmptyValueTag;
     }
 
     inline bool JSValue::operator==(const JSValue& other) const
     }
 
     inline bool JSValue::operator==(const JSValue& other) const
@@ -572,6 +604,11 @@ namespace JSC {
         return reinterpret_cast<JSCell*>(u.asBits.payload);
     }
 
         return reinterpret_cast<JSCell*>(u.asBits.payload);
     }
 
+    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d)
+    {
+        u.asDouble = d;
+    }
+
     inline JSValue::JSValue(ExecState* exec, double d)
     {
         const int32_t asInt32 = static_cast<int32_t>(d);
     inline JSValue::JSValue(ExecState* exec, double d)
     {
         const int32_t asInt32 = static_cast<int32_t>(d);
@@ -770,11 +807,17 @@ namespace JSC {
     inline JSValue::JSValue(JSCell* ptr)
         : m_ptr(ptr)
     {
     inline JSValue::JSValue(JSCell* ptr)
         : m_ptr(ptr)
     {
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie());
+#endif
     }
 
     inline JSValue::JSValue(const JSCell* ptr)
         : m_ptr(const_cast<JSCell*>(ptr))
     {
     }
 
     inline JSValue::JSValue(const JSCell* ptr)
         : m_ptr(const_cast<JSCell*>(ptr))
     {
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie());
+#endif
     }
 
     inline JSValue::operator bool() const
     }
 
     inline JSValue::operator bool() const
index a36cefacb0b424effc1c125e11788e44f22131ef..73650016a9f21c0b169a793ae11bae5c171b1286 100644 (file)
@@ -30,6 +30,7 @@
 #include "JSVariableObject.h"
 
 #include "PropertyNameArray.h"
 #include "JSVariableObject.h"
 
 #include "PropertyNameArray.h"
+#include "PropertyDescriptor.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -41,30 +42,30 @@ bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propert
     return JSObject::deleteProperty(exec, propertyName);
 }
 
     return JSObject::deleteProperty(exec, propertyName);
 }
 
-void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSVariableObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     SymbolTable::const_iterator end = symbolTable().end();
     for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
 {
     SymbolTable::const_iterator end = symbolTable().end();
     for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
-        if (!(it->second.getAttributes() & DontEnum))
+        if (!(it->second.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties))
             propertyNames.add(Identifier(exec, it->first.get()));
     }
     
             propertyNames.add(Identifier(exec, it->first.get()));
     }
     
-    JSObject::getPropertyNames(exec, propertyNames);
+    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
 }
 
 }
 
-bool JSVariableObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
+bool JSVariableObject::isVariableObject() const
 {
 {
-    SymbolTableEntry entry = symbolTable().get(propertyName.ustring().rep());
-    if (!entry.isNull()) {
-        attributes = entry.getAttributes() | DontDelete;
-        return true;
-    }
-    return JSObject::getPropertyAttributes(exec, propertyName, attributes);
+    return true;
 }
 
 }
 
-bool JSVariableObject::isVariableObject() const
+bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return true;
+    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+    if (!entry.isNull()) {
+        descriptor.setDescriptor(registerAt(entry.getIndex()).jsValue(), entry.getAttributes() | DontDelete);
+        return true;
+    }
+    return false;
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index b969da5e48bddcf031c09fee10a54f744e9df92e..6c679ce0720c58597f29d6bd10bf0ba9f9be0202 100644 (file)
@@ -49,16 +49,20 @@ namespace JSC {
         virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0;
 
         virtual bool deleteProperty(ExecState*, const Identifier&);
         virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0;
 
         virtual bool deleteProperty(ExecState*, const Identifier&);
-        virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
         
         virtual bool isVariableObject() const;
         virtual bool isDynamicScope() const = 0;
 
         
         virtual bool isVariableObject() const;
         virtual bool isDynamicScope() const = 0;
 
-        virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
-
         Register& registerAt(int index) const { return d->registers[index]; }
 
         Register& registerAt(int index) const { return d->registers[index]; }
 
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+        }
+        
     protected:
     protected:
+        static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags;
         // Subclasses of JSVariableObject can subclass this struct to add data
         // without increasing their own size (since there's a hard limit on the
         // size of a JSCell).
         // Subclasses of JSVariableObject can subclass this struct to add data
         // without increasing their own size (since there's a hard limit on the
         // size of a JSCell).
@@ -79,7 +83,7 @@ namespace JSC {
             JSVariableObjectData& operator=(const JSVariableObjectData&);
         };
 
             JSVariableObjectData& operator=(const JSVariableObjectData&);
         };
 
-        JSVariableObject(PassRefPtr<Structure> structure, JSVariableObjectData* data)
+        JSVariableObject(NonNullPassRefPtr<Structure> structure, JSVariableObjectData* data)
             : JSObject(structure)
             , d(data) // Subclass owns this pointer.
         {
             : JSObject(structure)
             , d(data) // Subclass owns this pointer.
         {
@@ -89,6 +93,7 @@ namespace JSC {
         void setRegisters(Register* r, Register* registerArray);
 
         bool symbolTableGet(const Identifier&, PropertySlot&);
         void setRegisters(Register* r, Register* registerArray);
 
         bool symbolTableGet(const Identifier&, PropertySlot&);
+        bool symbolTableGet(const Identifier&, PropertyDescriptor&);
         bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
         bool symbolTablePut(const Identifier&, JSValue);
         bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes);
         bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
         bool symbolTablePut(const Identifier&, JSValue);
         bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes);
index fb5701872d6d139f61a6f5f503f3830d25bd29c3..2c39f5c23849fee2affa194d4c6ee59399aba741 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2006 Maks Orlovich
 /*
  *  Copyright (C) 2006 Maks Orlovich
- *  Copyright (C) 2006 Apple Computer, Inc.
+ *  Copyright (C) 2006, 2009 Apple, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -26,11 +26,11 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
 
 
 ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
 
-void JSWrapperObject::mark(
+void JSWrapperObject::markChildren(MarkStack& markStack
 {
 {
-    JSObject::mark();
-    if (m_internalValue && !m_internalValue.marked())
-        m_internalValue.mark();
+    JSObject::markChildren(markStack);
+    if (m_internalValue)
+        markStack.append(m_internalValue);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 2a2e3c6ffdddabf0be3da80fb60f62b220c24455..f19cd30c85049409a338cce27f617e899ede340b 100644 (file)
 #include "JSObject.h"
 
 namespace JSC {
 #include "JSObject.h"
 
 namespace JSC {
-    
+
     // This class is used as a base for classes such as String,
     // Number, Boolean and Date which are wrappers for primitive types.
     class JSWrapperObject : public JSObject {
     protected:
     // This class is used as a base for classes such as String,
     // Number, Boolean and Date which are wrappers for primitive types.
     class JSWrapperObject : public JSObject {
     protected:
-        explicit JSWrapperObject(PassRefPtr<Structure>);
+        explicit JSWrapperObject(NonNullPassRefPtr<Structure>);
 
     public:
         JSValue internalValue() const { return m_internalValue; }
         void setInternalValue(JSValue);
 
     public:
         JSValue internalValue() const { return m_internalValue; }
         void setInternalValue(JSValue);
-        
-        virtual void mark();
-        
+
+        static PassRefPtr<Structure> createStructure(JSValue prototype) 
+        { 
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+        }
+
+    protected:
+        static const unsigned AnonymousSlotCount = 1 + JSObject::AnonymousSlotCount;
+
     private:
     private:
+        virtual void markChildren(MarkStack&);
+        
         JSValue m_internalValue;
     };
         JSValue m_internalValue;
     };
-    
-    inline JSWrapperObject::JSWrapperObject(PassRefPtr<Structure> structure)
+
+    inline JSWrapperObject::JSWrapperObject(NonNullPassRefPtr<Structure> structure)
         : JSObject(structure)
     {
         : JSObject(structure)
     {
+        putAnonymousValue(0, jsNull());
     }
     }
-    
+
     inline void JSWrapperObject::setInternalValue(JSValue value)
     {
         ASSERT(value);
         ASSERT(!value.isObject());
         m_internalValue = value;
     inline void JSWrapperObject::setInternalValue(JSValue value)
     {
         ASSERT(value);
         ASSERT(!value.isObject());
         m_internalValue = value;
+        putAnonymousValue(0, value);
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
diff --git a/runtime/JSZombie.cpp b/runtime/JSZombie.cpp
new file mode 100644 (file)
index 0000000..072d29b
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "JSZombie.h"
+#include "ClassInfo.h"
+
+#if ENABLE(JSC_ZOMBIES)
+
+namespace JSC {
+
+const ClassInfo JSZombie::s_info = { "Zombie", 0, 0, 0 };
+
+Structure* JSZombie::leakedZombieStructure() {
+    static Structure* structure = 0;
+    if (!structure) {
+        Structure::startIgnoringLeaks();
+        structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType)).releaseRef();
+        Structure::stopIgnoringLeaks();
+    }
+    return structure;
+}
+
+}
+
+#endif // ENABLE(JSC_ZOMBIES)
diff --git a/runtime/JSZombie.h b/runtime/JSZombie.h
new file mode 100644 (file)
index 0000000..8b33ea6
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef JSZombie_h
+#define JSZombie_h
+
+#include "JSCell.h"
+
+#if ENABLE(JSC_ZOMBIES)
+namespace JSC {
+
+class JSZombie : public JSCell {
+public:
+    JSZombie(const ClassInfo* oldInfo, Structure* structure)
+        : JSCell(structure)
+        , m_oldInfo(oldInfo)
+    {
+    }
+    virtual bool isZombie() const { return true; }
+    virtual const ClassInfo* classInfo() const { return &s_info; }
+    static Structure* leakedZombieStructure();
+
+    virtual bool isGetterSetter() const { ASSERT_NOT_REACHED(); return false; }
+    virtual bool isAPIValueWrapper() const { ASSERT_NOT_REACHED(); return false; }
+    virtual bool isPropertyNameIterator() const { ASSERT_NOT_REACHED(); return false; }
+    virtual CallType getCallData(CallData&) { ASSERT_NOT_REACHED(); return CallTypeNone; }
+    virtual ConstructType getConstructData(ConstructData&) { ASSERT_NOT_REACHED(); return ConstructTypeNone; }
+    virtual bool getUInt32(uint32_t&) const { ASSERT_NOT_REACHED(); return false; }
+    virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const { ASSERT_NOT_REACHED(); return jsNull(); }
+    virtual bool getPrimitiveNumber(ExecState*, double&, JSValue&) { ASSERT_NOT_REACHED(); return false; }
+    virtual bool toBoolean(ExecState*) const { ASSERT_NOT_REACHED(); return false; }
+    virtual double toNumber(ExecState*) const { ASSERT_NOT_REACHED(); return 0.0; }
+    virtual UString toString(ExecState*) const { ASSERT_NOT_REACHED(); return ""; }
+    virtual JSObject* toObject(ExecState*) const { ASSERT_NOT_REACHED(); return 0; }
+    virtual void markChildren(MarkStack&) { ASSERT_NOT_REACHED(); }
+    virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&) { ASSERT_NOT_REACHED(); }
+    virtual void put(ExecState*, unsigned, JSValue) { ASSERT_NOT_REACHED(); }
+    virtual bool deleteProperty(ExecState*, const Identifier&) { ASSERT_NOT_REACHED(); return false; }
+    virtual bool deleteProperty(ExecState*, unsigned) { ASSERT_NOT_REACHED(); return false; }
+    virtual JSObject* toThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return 0; }
+    virtual UString toThisString(ExecState*) const { ASSERT_NOT_REACHED(); return ""; }
+    virtual JSString* toThisJSString(ExecState*) { ASSERT_NOT_REACHED(); return 0; }
+    virtual JSValue getJSNumber() { ASSERT_NOT_REACHED(); return jsNull(); }
+    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&) { ASSERT_NOT_REACHED(); return false; }
+    virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&) { ASSERT_NOT_REACHED(); return false; }
+    
+    static const ClassInfo s_info;
+private:
+    const ClassInfo* m_oldInfo;
+};
+
+}
+
+#endif // ENABLE(JSC_ZOMBIES)
+
+#endif // JSZombie_h
index 798013a2fa6e8d0afd812085ebf89d3b5fda35ef..aa1e5ed9f63e63a76731b9cc068905470d54179e 100644 (file)
@@ -29,6 +29,7 @@
 #include "JSArray.h"
 #include "JSString.h"
 #include "Lexer.h"
 #include "JSArray.h"
 #include "JSString.h"
 #include "Lexer.h"
+#include "StringBuilder.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/dtoa.h>
 
 #include <wtf/ASCIICType.h>
 #include <wtf/dtoa.h>
 
@@ -129,52 +130,53 @@ template <LiteralParser::ParserMode mode> static inline bool isSafeStringCharact
     return (c >= ' ' && (mode == LiteralParser::StrictJSON || c <= 0xff) && c != '\\' && c != '"') || c == '\t';
 }
 
     return (c >= ' ' && (mode == LiteralParser::StrictJSON || c <= 0xff) && c != '\\' && c != '"') || c == '\t';
 }
 
-template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
+// "inline" is required here to help WINSCW compiler resolve specialized argument in templated functions.
+template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
 {
     ++m_ptr;
     const UChar* runStart;
 {
     ++m_ptr;
     const UChar* runStart;
-    token.stringToken = UString();
+    StringBuilder builder;
     do {
         runStart = m_ptr;
         while (m_ptr < m_end && isSafeStringCharacter<mode>(*m_ptr))
             ++m_ptr;
         if (runStart < m_ptr)
     do {
         runStart = m_ptr;
         while (m_ptr < m_end && isSafeStringCharacter<mode>(*m_ptr))
             ++m_ptr;
         if (runStart < m_ptr)
-            token.stringToken.append(runStart, m_ptr - runStart);
+            builder.append(runStart, m_ptr - runStart);
         if ((mode == StrictJSON) && m_ptr < m_end && *m_ptr == '\\') {
             ++m_ptr;
             if (m_ptr >= m_end)
                 return TokError;
             switch (*m_ptr) {
                 case '"':
         if ((mode == StrictJSON) && m_ptr < m_end && *m_ptr == '\\') {
             ++m_ptr;
             if (m_ptr >= m_end)
                 return TokError;
             switch (*m_ptr) {
                 case '"':
-                    token.stringToken.append('"');
+                    builder.append('"');
                     m_ptr++;
                     break;
                 case '\\':
                     m_ptr++;
                     break;
                 case '\\':
-                    token.stringToken.append('\\');
+                    builder.append('\\');
                     m_ptr++;
                     break;
                 case '/':
                     m_ptr++;
                     break;
                 case '/':
-                    token.stringToken.append('/');
+                    builder.append('/');
                     m_ptr++;
                     break;
                 case 'b':
                     m_ptr++;
                     break;
                 case 'b':
-                    token.stringToken.append('\b');
+                    builder.append('\b');
                     m_ptr++;
                     break;
                 case 'f':
                     m_ptr++;
                     break;
                 case 'f':
-                    token.stringToken.append('\f');
+                    builder.append('\f');
                     m_ptr++;
                     break;
                 case 'n':
                     m_ptr++;
                     break;
                 case 'n':
-                    token.stringToken.append('\n');
+                    builder.append('\n');
                     m_ptr++;
                     break;
                 case 'r':
                     m_ptr++;
                     break;
                 case 'r':
-                    token.stringToken.append('\r');
+                    builder.append('\r');
                     m_ptr++;
                     break;
                 case 't':
                     m_ptr++;
                     break;
                 case 't':
-                    token.stringToken.append('\t');
+                    builder.append('\t');
                     m_ptr++;
                     break;
 
                     m_ptr++;
                     break;
 
@@ -185,7 +187,7 @@ template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser
                         if (!isASCIIHexDigit(m_ptr[i]))
                             return TokError;
                     }
                         if (!isASCIIHexDigit(m_ptr[i]))
                             return TokError;
                     }
-                    token.stringToken.append(JSC::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
+                    builder.append(JSC::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
                     m_ptr += 5;
                     break;
 
                     m_ptr += 5;
                     break;
 
@@ -198,6 +200,7 @@ template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser
     if (m_ptr >= m_end || *m_ptr != '"')
         return TokError;
 
     if (m_ptr >= m_end || *m_ptr != '"')
         return TokError;
 
+    token.stringToken = builder.release();
     token.type = TokString;
     token.end = ++m_ptr;
     return TokString;
     token.type = TokString;
     token.end = ++m_ptr;
     return TokString;
@@ -294,7 +297,10 @@ JSValue LiteralParser::parse(ParserState initialState)
             }
             doParseArrayStartExpression:
             case DoParseArrayStartExpression: {
             }
             doParseArrayStartExpression:
             case DoParseArrayStartExpression: {
+                TokenType lastToken = m_lexer.currentToken().type;
                 if (m_lexer.next() == TokRBracket) {
                 if (m_lexer.next() == TokRBracket) {
+                    if (lastToken == TokComma)
+                        return JSValue();
                     m_lexer.next();
                     lastValue = objectStack.last();
                     objectStack.removeLast();
                     m_lexer.next();
                     lastValue = objectStack.last();
                     objectStack.removeLast();
index bceee7c1d5b21bc537bfe1d2d55b2cb08aa0c592..0f8072bd583d052931d616f9db809d660338a824 100644 (file)
@@ -89,7 +89,7 @@ namespace JSC {
             
         private:
             TokenType lex(LiteralParserToken&);
             
         private:
             TokenType lex(LiteralParserToken&);
-            template <ParserMode parserMode> TokenType lexString(LiteralParserToken&);
+            template <ParserMode mode> TokenType lexString(LiteralParserToken&);
             TokenType lexNumber(LiteralParserToken&);
             LiteralParserToken m_currentToken;
             UString m_string;
             TokenType lexNumber(LiteralParserToken&);
             LiteralParserToken m_currentToken;
             UString m_string;
index 8359ff7f6602aa7acc4ddfb5f4117a24038f065e..4e9e08602914721cfdd2e05e6dd33c6af4e06be5 100644 (file)
@@ -34,7 +34,7 @@ void HashTable::createTable(JSGlobalData* globalData) const
         entries[i].setKey(0);
     for (int i = 0; values[i].key; ++i) {
         UString::Rep* identifier = Identifier::add(globalData, values[i].key).releaseRef();
         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() & compactHashSizeMask;
+        int hashIndex = identifier->existingHash() & compactHashSizeMask;
         HashEntry* entry = &entries[hashIndex];
 
         if (entry->key()) {
         HashEntry* entry = &entries[hashIndex];
 
         if (entry->key()) {
index 167f2bc03018005828c5a555eb8ef0c6b2560e67..e673c09750e68c26a7028e7b33a94e388fe6a4f6 100644 (file)
@@ -51,7 +51,7 @@ namespace JSC {
     typedef PropertySlot::GetValueFunc GetFunction;
     typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value);
 
     typedef PropertySlot::GetValueFunc GetFunction;
     typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value);
 
-    class HashEntry {
+    class HashEntry : public FastAllocBase {
     public:
         void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2)
         {
     public:
         void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2)
         {
@@ -144,7 +144,7 @@ namespace JSC {
         {
             ASSERT(table);
 
         {
             ASSERT(table);
 
-            const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & compactHashSizeMask];
+            const HashEntry* entry = &table[identifier.ustring().rep()->existingHash() & compactHashSizeMask];
 
             if (!entry->key())
                 return 0;
 
             if (!entry->key())
                 return 0;
@@ -186,6 +186,24 @@ namespace JSC {
         return true;
     }
 
         return true;
     }
 
+    template <class ThisImp, class ParentImp>
+    inline bool getStaticPropertyDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
+    {
+        const HashEntry* entry = table->entry(exec, propertyName);
+        
+        if (!entry) // not found, forward to parent
+            return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+        PropertySlot slot;
+        if (entry->attributes() & Function)
+            setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
+        else
+            slot.setCustom(thisObj, entry->propertyGetter());
+
+        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+        return true;
+    }
+
     /**
      * Simplified version of getStaticPropertySlot in case there are only functions.
      * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing
     /**
      * Simplified version of getStaticPropertySlot in case there are only functions.
      * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing
@@ -204,6 +222,27 @@ namespace JSC {
         setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
         return true;
     }
         setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
         return true;
     }
+    
+    /**
+     * Simplified version of getStaticPropertyDescriptor in case there are only functions.
+     * Using this instead of getStaticPropertyDescriptor allows 'this' to avoid implementing
+     * a dummy getValueProperty.
+     */
+    template <class ParentImp>
+    inline bool getStaticFunctionDescriptor(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
+    {
+        if (static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor))
+            return true;
+        
+        const HashEntry* entry = table->entry(exec, propertyName);
+        if (!entry)
+            return false;
+        
+        PropertySlot slot;
+        setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
+        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+        return true;
+    }
 
     /**
      * Simplified version of getStaticPropertySlot in case there are no functions, only "values".
 
     /**
      * Simplified version of getStaticPropertySlot in case there are no functions, only "values".
@@ -223,6 +262,25 @@ namespace JSC {
         return true;
     }
 
         return true;
     }
 
+    /**
+     * Simplified version of getStaticPropertyDescriptor in case there are no functions, only "values".
+     * Using this instead of getStaticPropertyDescriptor removes the need for a FuncImp class.
+     */
+    template <class ThisImp, class ParentImp>
+    inline bool getStaticValueDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
+    {
+        const HashEntry* entry = table->entry(exec, propertyName);
+        
+        if (!entry) // not found, forward to parent
+            return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+        
+        ASSERT(!(entry->attributes() & Function));
+        PropertySlot slot;
+        slot.setCustom(thisObj, entry->propertyGetter());
+        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+        return true;
+    }
+
     /**
      * This one is for "put".
      * It looks up a hash entry for the property to be set.  If an entry
     /**
      * This one is for "put".
      * It looks up a hash entry for the property to be set.  If an entry
diff --git a/runtime/MarkStack.cpp b/runtime/MarkStack.cpp
new file mode 100644 (file)
index 0000000..a350c35
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "MarkStack.h"
+
+namespace JSC {
+
+size_t MarkStack::s_pageSize = 0;
+
+void MarkStack::compact()
+{
+    ASSERT(s_pageSize);
+    m_values.shrinkAllocation(s_pageSize);
+    m_markSets.shrinkAllocation(s_pageSize);
+}
+
+}
diff --git a/runtime/MarkStack.h b/runtime/MarkStack.h
new file mode 100644 (file)
index 0000000..c551bac
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef MarkStack_h
+#define MarkStack_h
+
+#include "JSValue.h"
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+    class JSGlobalData;
+    class Register;
+    
+    enum MarkSetProperties { MayContainNullValues, NoNullValues };
+    
+    class MarkStack : Noncopyable {
+    public:
+        MarkStack(void* jsArrayVPtr)
+            : m_jsArrayVPtr(jsArrayVPtr)
+#ifndef NDEBUG
+            , m_isCheckingForDefaultMarkViolation(false)
+#endif
+        {
+        }
+
+        ALWAYS_INLINE void append(JSValue);
+        void append(JSCell*);
+        
+        ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues)
+        {
+            appendValues(reinterpret_cast<JSValue*>(values), count, properties);
+        }
+
+        ALWAYS_INLINE void appendValues(JSValue* values, size_t count, MarkSetProperties properties = NoNullValues)
+        {
+            if (count)
+                m_markSets.append(MarkSet(values, values + count, properties));
+        }
+
+        inline void drain();
+        void compact();
+
+        ~MarkStack()
+        {
+            ASSERT(m_markSets.isEmpty());
+            ASSERT(m_values.isEmpty());
+        }
+
+    private:
+        void markChildren(JSCell*);
+
+        struct MarkSet {
+            MarkSet(JSValue* values, JSValue* end, MarkSetProperties properties)
+                : m_values(values)
+                , m_end(end)
+                , m_properties(properties)
+            {
+                ASSERT(values);
+            }
+            JSValue* m_values;
+            JSValue* m_end;
+            MarkSetProperties m_properties;
+        };
+
+        static void* allocateStack(size_t size);
+        static void releaseStack(void* addr, size_t size);
+
+        static void initializePagesize();
+        static size_t pageSize()
+        {
+            if (!s_pageSize)
+                initializePagesize();
+            return s_pageSize;
+        }
+
+        template <typename T> struct MarkStackArray {
+            MarkStackArray()
+                : m_top(0)
+                , m_allocated(MarkStack::pageSize())
+                , m_capacity(m_allocated / sizeof(T))
+            {
+                m_data = reinterpret_cast<T*>(allocateStack(m_allocated));
+            }
+
+            ~MarkStackArray()
+            {
+                releaseStack(m_data, m_allocated);
+            }
+
+            void expand()
+            {
+                size_t oldAllocation = m_allocated;
+                m_allocated *= 2;
+                m_capacity = m_allocated / sizeof(T);
+                void* newData = allocateStack(m_allocated);
+                memcpy(newData, m_data, oldAllocation);
+                releaseStack(m_data, oldAllocation);
+                m_data = reinterpret_cast<T*>(newData);
+            }
+
+            inline void append(const T& v)
+            {
+                if (m_top == m_capacity)
+                    expand();
+                m_data[m_top++] = v;
+            }
+
+            inline T removeLast()
+            {
+                ASSERT(m_top);
+                return m_data[--m_top];
+            }
+            
+            inline T& last()
+            {
+                ASSERT(m_top);
+                return m_data[m_top - 1];
+            }
+
+            inline bool isEmpty()
+            {
+                return m_top == 0;
+            }
+
+            inline size_t size() { return m_top; }
+
+            inline void shrinkAllocation(size_t size)
+            {
+                ASSERT(size <= m_allocated);
+                ASSERT(0 == (size % MarkStack::pageSize()));
+                if (size == m_allocated)
+                    return;
+#if OS(WINDOWS) || OS(SYMBIAN) || PLATFORM(BREWMP)
+                // We cannot release a part of a region with VirtualFree.  To get around this,
+                // we'll release the entire region and reallocate the size that we want.
+                releaseStack(m_data, m_allocated);
+                m_data = reinterpret_cast<T*>(allocateStack(size));
+#else
+                releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size);
+#endif
+                m_allocated = size;
+                m_capacity = m_allocated / sizeof(T);
+            }
+
+        private:
+            size_t m_top;
+            size_t m_allocated;
+            size_t m_capacity;
+            T* m_data;
+        };
+
+        void* m_jsArrayVPtr;
+        MarkStackArray<MarkSet> m_markSets;
+        MarkStackArray<JSCell*> m_values;
+        static size_t s_pageSize;
+
+#ifndef NDEBUG
+    public:
+        bool m_isCheckingForDefaultMarkViolation;
+#endif
+    };
+}
+
+#endif
diff --git a/runtime/MarkStackNone.cpp b/runtime/MarkStackNone.cpp
new file mode 100644 (file)
index 0000000..b1ff48b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "MarkStack.h"
+
+#include "FastMalloc.h"
+
+namespace JSC {
+
+void MarkStack::initializePagesize()
+{
+    MarkStack::s_pageSize = 4096;
+}
+
+void* MarkStack::allocateStack(size_t size)
+{
+    return fastMalloc(size);
+}
+
+void MarkStack::releaseStack(void* addr, size_t)
+{
+    return fastFree(addr);
+}
+
+}
diff --git a/runtime/MarkStackPosix.cpp b/runtime/MarkStackPosix.cpp
new file mode 100644 (file)
index 0000000..c28bc0d
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "MarkStack.h"
+
+#if OS(UNIX) && !OS(SYMBIAN)
+
+#include <unistd.h>
+#include <sys/mman.h>
+
+namespace JSC {
+
+void MarkStack::initializePagesize()
+{
+    MarkStack::s_pageSize = getpagesize();
+}
+
+void* MarkStack::allocateStack(size_t size)
+{
+    return mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+}
+void MarkStack::releaseStack(void* addr, size_t size)
+{
+    munmap(addr, size);
+}
+
+}
+
+#endif
diff --git a/runtime/MarkStackSymbian.cpp b/runtime/MarkStackSymbian.cpp
new file mode 100644 (file)
index 0000000..bda14ac
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "MarkStack.h"
+
+#if OS(SYMBIAN)
+
+#include <e32hal.h>
+
+namespace JSC {
+
+void MarkStack::initializePagesize()
+{
+    TInt page_size;
+    UserHal::PageSizeInBytes(page_size);
+    MarkStack::s_pageSize = page_size;
+}
+
+void* MarkStack::allocateStack(size_t size)
+{
+    return fastMalloc(size);
+}
+
+void MarkStack::releaseStack(void* addr, size_t size)
+{
+    return fastFree(addr);
+}
+
+}
+
+#endif
diff --git a/runtime/MarkStackWin.cpp b/runtime/MarkStackWin.cpp
new file mode 100644 (file)
index 0000000..a171c78
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "MarkStack.h"
+
+#if OS(WINDOWS)
+
+#include "windows.h"
+
+namespace JSC {
+
+void MarkStack::initializePagesize()
+{
+    SYSTEM_INFO system_info;
+    GetSystemInfo(&system_info);
+    MarkStack::s_pageSize = system_info.dwPageSize;
+}
+
+void* MarkStack::allocateStack(size_t size)
+{
+    return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+}
+void MarkStack::releaseStack(void* addr, size_t)
+{
+    // According to http://msdn.microsoft.com/en-us/library/aa366892(VS.85).aspx,
+    // dwSize must be 0 if dwFreeType is MEM_RELEASE.
+    VirtualFree(addr, 0, MEM_RELEASE);
+}
+
+}
+
+#endif
index 2572bc9ac079aab44841e194ad8aac9e49b25b56..98ff3ba8b3cb7f82f836ed0f7a1509aa773e87cb 100644 (file)
@@ -85,7 +85,7 @@ const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
 @end
 */
 
 @end
 */
 
-MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure)
+MathObject::MathObject(ExecState* exec, NonNullPassRefPtr<Structure> structure)
     : JSObject(structure)
 {
     putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exec, exp(1.0)), DontDelete | DontEnum | ReadOnly);
     : JSObject(structure)
 {
     putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exec, exp(1.0)), DontDelete | DontEnum | ReadOnly);
@@ -96,21 +96,18 @@ MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure)
     putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(exec, piDouble), DontDelete | DontEnum | ReadOnly);
     putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(exec, sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
     putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(exec, sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
     putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(exec, piDouble), DontDelete | DontEnum | ReadOnly);
     putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(exec, sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
     putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(exec, sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
-    WTF::initializeWeakRandomNumberGenerator();
 }
 
 // ECMA 15.8
 
 bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 }
 
 // ECMA 15.8
 
 bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
-    const HashEntry* entry = ExecState::mathTable(exec)->entry(exec, propertyName);
-
-    if (!entry)
-        return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+    return getStaticFunctionSlot<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, slot);
+}
 
 
-    ASSERT(entry->attributes() & Function);
-    setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
-    return true;
+bool MathObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, descriptor);
 }
 
 // ------------------------------ Functions --------------------------------
 }
 
 // ------------------------------ Functions --------------------------------
@@ -122,22 +119,22 @@ JSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState* exec, JSObject*, JSValue, cons
 
 JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 
 JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, acos(args.at(0).toNumber(exec)));
+    return jsDoubleNumber(exec, acos(args.at(0).toNumber(exec)));
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, asin(args.at(0).toNumber(exec)));
+    return jsDoubleNumber(exec, asin(args.at(0).toNumber(exec)));
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, atan(args.at(0).toNumber(exec)));
+    return jsDoubleNumber(exec, atan(args.at(0).toNumber(exec)));
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, atan2(args.at(0).toNumber(exec), args.at(1).toNumber(exec)));
+    return jsDoubleNumber(exec, atan2(args.at(0).toNumber(exec), args.at(1).toNumber(exec)));
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue, const ArgList& args)
@@ -147,12 +144,12 @@ JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue, con
 
 JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 
 JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, cos(args.at(0).toNumber(exec)));
+    return jsDoubleNumber(exec, cos(args.at(0).toNumber(exec)));
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, exp(args.at(0).toNumber(exec)));
+    return jsDoubleNumber(exec, exp(args.at(0).toNumber(exec)));
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
@@ -162,7 +159,7 @@ JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue, co
 
 JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 
 JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, log(args.at(0).toNumber(exec)));
+    return jsDoubleNumber(exec, log(args.at(0).toNumber(exec)));
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec, JSObject*, JSValue, const ArgList& args)
@@ -213,7 +210,7 @@ JSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec, JSObject*, JSValue, cons
 
 JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue, const ArgList&)
 {
 
 JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue, const ArgList&)
 {
-    return jsNumber(exec, WTF::weakRandomNumber());
+    return jsDoubleNumber(exec, exec->globalData().weakRandom.get());
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, const ArgList& args)
@@ -226,17 +223,17 @@ JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, co
 
 JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 
 JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, sin(args.at(0).toNumber(exec)));
+    return jsDoubleNumber(exec, sin(args.at(0).toNumber(exec)));
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, sqrt(args.at(0).toNumber(exec)));
+    return jsDoubleNumber(exec, sqrt(args.at(0).toNumber(exec)));
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
 }
 
 JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 {
-    return jsNumber(exec, tan(args.at(0).toNumber(exec)));
+    return jsDoubleNumber(exec, tan(args.at(0).toNumber(exec)));
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 3557d1ecaa7c04ce5c58dd9fb45aef8373524c6a..a9f70313d4feab9e12b30d484b4d588b9ec95df5 100644 (file)
@@ -27,17 +27,21 @@ namespace JSC {
 
     class MathObject : public JSObject {
     public:
 
     class MathObject : public JSObject {
     public:
-        MathObject(ExecState*, PassRefPtr<Structure>);
+        MathObject(ExecState*, NonNullPassRefPtr<Structure>);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType));
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
         }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 0205fc55d4cc796f708a629e50f4e125ef4a2116..403fc7ecca463e62c6b18491868bae817007d54a 100644 (file)
@@ -32,8 +32,8 @@ ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor);
 
 const ClassInfo NativeErrorConstructor::info = { "Function", &InternalFunction::info, 0, 0 };
 
 
 const ClassInfo NativeErrorConstructor::info = { "Function", &InternalFunction::info, 0, 0 };
 
-NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, NativeErrorPrototype* nativeErrorPrototype)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name).getString()))
+NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, NativeErrorPrototype* nativeErrorPrototype)
+    : InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name).getString(exec)))
     , m_errorStructure(ErrorInstance::createStructure(nativeErrorPrototype))
 {
     putDirect(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
     , m_errorStructure(ErrorInstance::createStructure(nativeErrorPrototype))
 {
     putDirect(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
index 118d1f43ddf746918e99d363a97156a61cc0ccf6..152dbac2f5a72647ab5e9893587154aa0e4961b8 100644 (file)
@@ -31,7 +31,7 @@ namespace JSC {
 
     class NativeErrorConstructor : public InternalFunction {
     public:
 
     class NativeErrorConstructor : public InternalFunction {
     public:
-        NativeErrorConstructor(ExecState*, PassRefPtr<Structure>, NativeErrorPrototype*);
+        NativeErrorConstructor(ExecState*, NonNullPassRefPtr<Structure>, NativeErrorPrototype*);
 
         static const ClassInfo info;
 
 
         static const ClassInfo info;
 
index 84190a0df19de1440a7887f3f480f7a92cdf1c7e..aa46a6a4292f4e965b4d99abaad7ad19b82d3790 100644 (file)
@@ -29,7 +29,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype);
 
 
 ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype);
 
-NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, const UString& name, const UString& message)
+NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& name, const UString& message)
     : JSObject(structure)
 {
     putDirect(exec->propertyNames().name, jsString(exec, name), 0);
     : JSObject(structure)
 {
     putDirect(exec->propertyNames().name, jsString(exec, name), 0);
index 77bfe8a271c53f830fc91e0fdde4d6da5ed92fa8..0c65a9c3e45b935227b5b6a20a949ae40401a55a 100644 (file)
@@ -27,7 +27,7 @@ namespace JSC {
 
     class NativeErrorPrototype : public JSObject {
     public:
 
     class NativeErrorPrototype : public JSObject {
     public:
-        NativeErrorPrototype(ExecState*, PassRefPtr<Structure>, const UString& name, const UString& message);
+        NativeErrorPrototype(ExecState*, NonNullPassRefPtr<Structure>, const UString& name, const UString& message);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 2840bf0b2cf2ac754859b105fa3b3982378987c5..cc6c51d4ea59fae4a14122d534430438236d1c09 100644 (file)
@@ -53,7 +53,7 @@ const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info,
 @end
 */
 
 @end
 */
 
-NumberConstructor::NumberConstructor(ExecState* exec, PassRefPtr<Structure> structure, NumberPrototype* numberPrototype)
+NumberConstructor::NumberConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, NumberPrototype* numberPrototype)
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, numberPrototype->info.className))
 {
     // Number.Prototype
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, numberPrototype->info.className))
 {
     // Number.Prototype
@@ -68,6 +68,11 @@ bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& pr
     return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot);
 }
 
     return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot);
 }
 
+bool NumberConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticValueDescriptor<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, descriptor);
+}
+
 static JSValue numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&)
 {
     return jsNaN(exec);
 static JSValue numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&)
 {
     return jsNaN(exec);
index b1224ec552d073908cc559efc13dc4dd9ac3ca7a..723c4b283152b01030225e3fae71b50fe926b918 100644 (file)
@@ -29,20 +29,24 @@ namespace JSC {
 
     class NumberConstructor : public InternalFunction {
     public:
 
     class NumberConstructor : public InternalFunction {
     public:
-        NumberConstructor(ExecState*, PassRefPtr<Structure>, NumberPrototype*);
+        NumberConstructor(ExecState*, NonNullPassRefPtr<Structure>, NumberPrototype*);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
         JSValue getValueProperty(ExecState*, int token) const;
 
         static const ClassInfo info;
 
         static PassRefPtr<Structure> createStructure(JSValue proto) 
         { 
         JSValue getValueProperty(ExecState*, int token) const;
 
         static const ClassInfo info;
 
         static PassRefPtr<Structure> createStructure(JSValue proto) 
         { 
-            return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance)); 
+            return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
         }
 
         enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
 
         }
 
         enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
 
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | InternalFunction::StructureFlags;
+
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
index 0e8df1730fff84c4ba5c1525526cabf112b8c853..1a7e44ccedfd925eb1a5941a93d1775e21d2f2c9 100644 (file)
@@ -31,7 +31,7 @@ ASSERT_CLASS_FITS_IN_CELL(NumberObject);
 
 const ClassInfo NumberObject::info = { "Number", 0, 0, 0 };
 
 
 const ClassInfo NumberObject::info = { "Number", 0, 0, 0 };
 
-NumberObject::NumberObject(PassRefPtr<Structure> structure)
+NumberObject::NumberObject(NonNullPassRefPtr<Structure> structure)
     : JSWrapperObject(structure)
 {
 }
     : JSWrapperObject(structure)
 {
 }
index d354b9b8a2a8609ed7283c9b7ff1016d23bbe1fc..6c18cdd3bfa441ca588bd8b7cbb7e8c5ebdfb749 100644 (file)
@@ -27,10 +27,22 @@ namespace JSC {
 
     class NumberObject : public JSWrapperObject {
     public:
 
     class NumberObject : public JSWrapperObject {
     public:
-        explicit NumberObject(PassRefPtr<Structure>);
+        explicit NumberObject(NonNullPassRefPtr<Structure>);
 
         static const ClassInfo info;
 
 
         static const ClassInfo info;
 
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+        }
+
+    protected:
+#if USE(JSVALUE32)
+        static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags;
+#else
+        static const unsigned StructureFlags = JSWrapperObject::StructureFlags;
+#endif
+
     private:
         virtual const ClassInfo* classInfo() const { return &info; }
 
     private:
         virtual const ClassInfo* classInfo() const { return &info; }
 
index d8be4e4aaaf346ddbcfb165443907b757b926d29..3ecc78628a5bd9908cf67767a1443ff009d1e356 100644 (file)
 #include "Error.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "Error.h"
 #include "JSFunction.h"
 #include "JSString.h"
+#include "Operations.h"
 #include "PrototypeFunction.h"
 #include "PrototypeFunction.h"
+#include "StringBuilder.h"
 #include "dtoa.h"
 #include "dtoa.h"
-#include "Operations.h"
 #include <wtf/Assertions.h>
 #include <wtf/MathExtras.h>
 #include <wtf/Vector.h>
 #include <wtf/Assertions.h>
 #include <wtf/MathExtras.h>
 #include <wtf/Vector.h>
@@ -45,7 +46,7 @@ static JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*, JSObject*, J
 
 // ECMA 15.7.4
 
 
 // ECMA 15.7.4
 
-NumberPrototype::NumberPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+NumberPrototype::NumberPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
     : NumberObject(structure)
 {
     setInternalValue(jsNumber(exec, 0));
     : NumberObject(structure)
 {
     setInternalValue(jsNumber(exec, 0));
@@ -73,11 +74,12 @@ static UString integerPartNoExp(double d)
     bool resultIsInfOrNan = (decimalPoint == 9999);
     size_t length = strlen(result);
 
     bool resultIsInfOrNan = (decimalPoint == 9999);
     size_t length = strlen(result);
 
-    UString str = sign ? "-" : "";
+    StringBuilder builder;
+    builder.append(sign ? "-" : "");
     if (resultIsInfOrNan)
     if (resultIsInfOrNan)
-        str += result;
+        builder.append((const char*)result);
     else if (decimalPoint <= 0)
     else if (decimalPoint <= 0)
-        str += "0";
+        builder.append("0");
     else {
         Vector<char, 1024> buf(decimalPoint + 1);
 
     else {
         Vector<char, 1024> buf(decimalPoint + 1);
 
@@ -90,10 +92,10 @@ static UString integerPartNoExp(double d)
             strncpy(buf.data(), result, decimalPoint);
         buf[decimalPoint] = '\0';
 
             strncpy(buf.data(), result, decimalPoint);
         buf[decimalPoint] = '\0';
 
-        str.append(buf.data());
+        builder.append((const char*)(buf.data()));
     }
 
     }
 
-    return str;
+    return builder.release();
 }
 
 static UString charSequence(char c, int count)
 }
 
 static UString charSequence(char c, int count)
@@ -237,13 +239,16 @@ JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue
 
     UString s;
     if (x < 0) {
 
     UString s;
     if (x < 0) {
-        s.append('-');
+        s = "-";
         x = -x;
         x = -x;
-    } else if (x == -0.0)
-        x = 0;
+    } else {
+        s = "";
+        if (x == -0.0)
+            x = 0;
+    }
 
     if (x >= pow(10.0, 21.0))
 
     if (x >= pow(10.0, 21.0))
-        return jsString(exec, s + UString::from(x));
+        return jsString(exec, makeString(s, UString::from(x)));
 
     const double tenToTheF = pow(10.0, f);
     double n = floor(x * tenToTheF);
 
     const double tenToTheF = pow(10.0, f);
     double n = floor(x * tenToTheF);
@@ -254,17 +259,19 @@ JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue
 
     int k = m.size();
     if (k <= f) {
 
     int k = m.size();
     if (k <= f) {
-        UString z;
+        StringBuilder z;
         for (int i = 0; i < f + 1 - k; i++)
             z.append('0');
         for (int i = 0; i < f + 1 - k; i++)
             z.append('0');
-        m = z + m;
+        z.append(m);
+        m = z.release();
         k = f + 1;
         ASSERT(k == m.size());
     }
     int kMinusf = k - f;
         k = f + 1;
         ASSERT(k == m.size());
     }
     int kMinusf = k - f;
+
     if (kMinusf < m.size())
     if (kMinusf < m.size())
-        return jsString(exec, s + m.substr(0, kMinusf) + "." + m.substr(kMinusf));
-    return jsString(exec, s + m.substr(0, kMinusf));
+        return jsString(exec, makeString(s, m.substr(0, kMinusf), ".", m.substr(kMinusf)));
+    return jsString(exec, makeString(s, m.substr(0, kMinusf)));
 }
 
 static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits)
 }
 
 static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits)
@@ -392,7 +399,8 @@ JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSV
     if (x < 0) {
         s = "-";
         x = -x;
     if (x < 0) {
         s = "-";
         x = -x;
-    }
+    } else
+        s = "";
 
     if (!(doublePrecision >= 1 && doublePrecision <= 21)) // true for NaN
         return throwError(exec, RangeError, "toPrecision() argument must be between 1 and 21");
 
     if (!(doublePrecision >= 1 && doublePrecision <= 21)) // true for NaN
         return throwError(exec, RangeError, "toPrecision() argument must be between 1 and 21");
@@ -423,10 +431,10 @@ JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSV
         m = integerPartNoExp(n);
         if (e < -6 || e >= precision) {
             if (m.size() > 1)
         m = integerPartNoExp(n);
         if (e < -6 || e >= precision) {
             if (m.size() > 1)
-                m = m.substr(0, 1) + "." + m.substr(1);
+                m = makeString(m.substr(0, 1), ".", m.substr(1));
             if (e >= 0)
             if (e >= 0)
-                return jsNontrivialString(exec, s + m + "e+" + UString::from(e));
-            return jsNontrivialString(exec, s + m + "e-" + UString::from(-e));
+                return jsNontrivialString(exec, makeString(s, m, "e+", UString::from(e)));
+            return jsNontrivialString(exec, makeString(s, m, "e-", UString::from(-e)));
         }
     } else {
         m = charSequence('0', precision);
         }
     } else {
         m = charSequence('0', precision);
@@ -434,13 +442,13 @@ JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSV
     }
 
     if (e == precision - 1)
     }
 
     if (e == precision - 1)
-        return jsString(exec, s + m);
+        return jsString(exec, makeString(s, m));
     if (e >= 0) {
         if (e + 1 < m.size())
     if (e >= 0) {
         if (e + 1 < m.size())
-            return jsString(exec, s + m.substr(0, e + 1) + "." + m.substr(e + 1));
-        return jsString(exec, s + m);
+            return jsString(exec, makeString(s, m.substr(0, e + 1), ".", m.substr(e + 1)));
+        return jsString(exec, makeString(s, m));
     }
     }
-    return jsNontrivialString(exec, s + "0." + charSequence('0', -(e + 1)) + m);
+    return jsNontrivialString(exec, makeString(s, "0.", charSequence('0', -(e + 1)), m));
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 0a3a5442c320a825164cc727b7ed4e7f118cc3ec..1fb20771e022126a66dcc244e2438001eae76b37 100644 (file)
@@ -27,7 +27,7 @@ namespace JSC {
 
     class NumberPrototype : public NumberObject {
     public:
 
     class NumberPrototype : public NumberObject {
     public:
-        NumberPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+        NumberPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
diff --git a/runtime/NumericStrings.h b/runtime/NumericStrings.h
new file mode 100644 (file)
index 0000000..c0696a4
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NumericStrings_h
+#define NumericStrings_h
+
+#include "UString.h"
+#include <wtf/HashFunctions.h>
+
+namespace JSC {
+
+    class NumericStrings {
+    public:
+        UString add(double d)
+        {
+            CacheEntry<double>& entry = lookup(d);
+            if (d == entry.key && !entry.value.isNull())
+                return entry.value;
+            entry.key = d;
+            entry.value = UString::from(d);
+            return entry.value;
+        }
+
+        UString add(int i)
+        {
+            CacheEntry<int>& entry = lookup(i);
+            if (i == entry.key && !entry.value.isNull())
+                return entry.value;
+            entry.key = i;
+            entry.value = UString::from(i);
+            return entry.value;
+        }
+
+    private:
+        static const size_t cacheSize = 64;
+
+        template<typename T>
+        struct CacheEntry {
+            T key;
+            UString value;
+        };
+
+        CacheEntry<double>& lookup(double d) { return doubleCache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; }
+        CacheEntry<int>& lookup(int i) { return intCache[WTF::IntHash<int>::hash(i) & (cacheSize - 1)]; }
+
+        CacheEntry<double> doubleCache[cacheSize];
+        CacheEntry<int> intCache[cacheSize];
+    };
+
+} // namespace JSC
+
+#endif // NumericStrings_h
index cf1790f061c260790569d67851aca8c89712f3ac..0838eb43755004b579d6347b09b476a0a0ba93cf 100644 (file)
 #include "config.h"
 #include "ObjectConstructor.h"
 
 #include "config.h"
 #include "ObjectConstructor.h"
 
+#include "Error.h"
 #include "JSFunction.h"
 #include "JSFunction.h"
+#include "JSArray.h"
 #include "JSGlobalObject.h"
 #include "ObjectPrototype.h"
 #include "JSGlobalObject.h"
 #include "ObjectPrototype.h"
+#include "PropertyDescriptor.h"
+#include "PropertyNameArray.h"
+#include "PrototypeFunction.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor);
 
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor);
 
-ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
+static JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorKeys(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorCreate(ExecState*, JSObject*, JSValue, const ArgList&);
+
+ObjectConstructor::ObjectConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure)
+: InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
 {
     // ECMA 15.2.3.1
     putDirectWithoutTransition(exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
 {
     // ECMA 15.2.3.1
     putDirectWithoutTransition(exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
-
+    
     // no. of arguments for constructor
     putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
     // no. of arguments for constructor
     putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+    
+    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum);
+    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum);
+    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getOwnPropertyNames, objectConstructorGetOwnPropertyNames), DontEnum);
+    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().keys, objectConstructorKeys), DontEnum);
+    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 3, exec->propertyNames().defineProperty, objectConstructorDefineProperty), DontEnum);
+    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().defineProperties, objectConstructorDefineProperties), DontEnum);
+    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().create, objectConstructorCreate), DontEnum);
 }
 
 // ECMA 15.2.2
 }
 
 // ECMA 15.2.2
@@ -70,4 +91,227 @@ CallType ObjectConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
     return CallTypeHost;
 }
 
+JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+    if (!args.at(0).isObject())
+        return throwError(exec, TypeError, "Requested prototype of a value that is not an object.");
+    return asObject(args.at(0))->prototype();
+}
+
+JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+    if (!args.at(0).isObject())
+        return throwError(exec, TypeError, "Requested property descriptor of a value that is not an object.");
+    UString propertyName = args.at(1).toString(exec);
+    if (exec->hadException())
+        return jsNull();
+    JSObject* object = asObject(args.at(0));
+    PropertyDescriptor descriptor;
+    if (!object->getOwnPropertyDescriptor(exec, Identifier(exec, propertyName), descriptor))
+        return jsUndefined();
+    if (exec->hadException())
+        return jsUndefined();
+
+    JSObject* description = constructEmptyObject(exec);
+    if (!descriptor.isAccessorDescriptor()) {
+        description->putDirect(exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
+        description->putDirect(exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
+    } else {
+        description->putDirect(exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0);
+        description->putDirect(exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0);
+    }
+    
+    description->putDirect(exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
+    description->putDirect(exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0);
+
+    return description;
+}
+
+// FIXME: Use the enumeration cache.
+JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+    if (!args.at(0).isObject())
+        return throwError(exec, TypeError, "Requested property names of a value that is not an object.");
+    PropertyNameArray properties(exec);
+    asObject(args.at(0))->getOwnPropertyNames(exec, properties, IncludeDontEnumProperties);
+    JSArray* names = constructEmptyArray(exec);
+    size_t numProperties = properties.size();
+    for (size_t i = 0; i < numProperties; i++)
+        names->push(exec, jsOwnedString(exec, properties[i].ustring()));
+    return names;
+}
+
+// FIXME: Use the enumeration cache.
+JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+    if (!args.at(0).isObject())
+        return throwError(exec, TypeError, "Requested keys of a value that is not an object.");
+    PropertyNameArray properties(exec);
+    asObject(args.at(0))->getOwnPropertyNames(exec, properties);
+    JSArray* keys = constructEmptyArray(exec);
+    size_t numProperties = properties.size();
+    for (size_t i = 0; i < numProperties; i++)
+        keys->push(exec, jsOwnedString(exec, properties[i].ustring()));
+    return keys;
+}
+
+// ES5 8.10.5 ToPropertyDescriptor
+static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
+{
+    if (!in.isObject()) {
+        throwError(exec, TypeError, "Property description must be an object.");
+        return false;
+    }
+    JSObject* description = asObject(in);
+
+    PropertySlot enumerableSlot(description);
+    if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) {
+        desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec));
+        if (exec->hadException())
+            return false;
+    }
+
+    PropertySlot configurableSlot(description);
+    if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) {
+        desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec));
+        if (exec->hadException())
+            return false;
+    }
+
+    JSValue value;
+    PropertySlot valueSlot(description);
+    if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) {
+        desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value));
+        if (exec->hadException())
+            return false;
+    }
+
+    PropertySlot writableSlot(description);
+    if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) {
+        desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec));
+        if (exec->hadException())
+            return false;
+    }
+
+    PropertySlot getSlot(description);
+    if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) {
+        JSValue get = getSlot.getValue(exec, exec->propertyNames().get);
+        if (exec->hadException())
+            return false;
+        if (!get.isUndefined()) {
+            CallData callData;
+            if (get.getCallData(callData) == CallTypeNone) {
+                throwError(exec, TypeError, "Getter must be a function.");
+                return false;
+            }
+        } else
+            get = JSValue();
+        desc.setGetter(get);
+    }
+
+    PropertySlot setSlot(description);
+    if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) {
+        JSValue set = setSlot.getValue(exec, exec->propertyNames().set);
+        if (exec->hadException())
+            return false;
+        if (!set.isUndefined()) {
+            CallData callData;
+            if (set.getCallData(callData) == CallTypeNone) {
+                throwError(exec, TypeError, "Setter must be a function.");
+                return false;
+            }
+        } else
+            set = JSValue();
+
+        desc.setSetter(set);
+    }
+
+    if (!desc.isAccessorDescriptor())
+        return true;
+
+    if (desc.value()) {
+        throwError(exec, TypeError, "Invalid property.  'value' present on property with getter or setter.");
+        return false;
+    }
+
+    if (desc.writablePresent()) {
+        throwError(exec, TypeError, "Invalid property.  'writable' present on property with getter or setter.");
+        return false;
+    }
+    return true;
+}
+
+JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+    if (!args.at(0).isObject())
+        return throwError(exec, TypeError, "Properties can only be defined on Objects.");
+    JSObject* O = asObject(args.at(0));
+    UString propertyName = args.at(1).toString(exec);
+    if (exec->hadException())
+        return jsNull();
+    PropertyDescriptor descriptor;
+    if (!toPropertyDescriptor(exec, args.at(2), descriptor))
+        return jsNull();
+    ASSERT((descriptor.attributes() & (Getter | Setter)) || (!descriptor.isAccessorDescriptor()));
+    ASSERT(!exec->hadException());
+    O->defineOwnProperty(exec, Identifier(exec, propertyName), descriptor, true);
+    return O;
+}
+
+static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
+{
+    PropertyNameArray propertyNames(exec);
+    asObject(properties)->getOwnPropertyNames(exec, propertyNames);
+    size_t numProperties = propertyNames.size();
+    Vector<PropertyDescriptor> descriptors;
+    MarkedArgumentBuffer markBuffer;
+    for (size_t i = 0; i < numProperties; i++) {
+        PropertySlot slot;
+        JSValue prop = properties->get(exec, propertyNames[i]);
+        if (exec->hadException())
+            return jsNull();
+        PropertyDescriptor descriptor;
+        if (!toPropertyDescriptor(exec, prop, descriptor))
+            return jsNull();
+        descriptors.append(descriptor);
+        // Ensure we mark all the values that we're accumulating
+        if (descriptor.isDataDescriptor() && descriptor.value())
+            markBuffer.append(descriptor.value());
+        if (descriptor.isAccessorDescriptor()) {
+            if (descriptor.getter())
+                markBuffer.append(descriptor.getter());
+            if (descriptor.setter())
+                markBuffer.append(descriptor.setter());
+        }
+    }
+    for (size_t i = 0; i < numProperties; i++) {
+        object->defineOwnProperty(exec, propertyNames[i], descriptors[i], true);
+        if (exec->hadException())
+            return jsNull();
+    }
+    return object;
+}
+
+JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+    if (!args.at(0).isObject())
+        return throwError(exec, TypeError, "Properties can only be defined on Objects.");
+    if (!args.at(1).isObject())
+        return throwError(exec, TypeError, "Property descriptor list must be an Object.");
+    return defineProperties(exec, asObject(args.at(0)), asObject(args.at(1)));
+}
+
+JSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+    if (!args.at(0).isObject() && !args.at(0).isNull())
+        return throwError(exec, TypeError, "Object prototype may only be an Object or null.");
+    JSObject* newObject = constructEmptyObject(exec);
+    newObject->setPrototype(args.at(0));
+    if (args.at(1).isUndefined())
+        return newObject;
+    if (!args.at(1).isObject())
+        return throwError(exec, TypeError, "Property descriptor list must be an Object.");
+    return defineProperties(exec, newObject, asObject(args.at(1)));
+}
+
 } // namespace JSC
 } // namespace JSC
index f8c058a139d615a0173bb49fb99986ed2a8a0942..1d2cddeacca5cee733d363aea6b26fd2a81457fa 100644 (file)
@@ -29,7 +29,7 @@ namespace JSC {
 
     class ObjectConstructor : public InternalFunction {
     public:
 
     class ObjectConstructor : public InternalFunction {
     public:
-        ObjectConstructor(ExecState*, PassRefPtr<Structure>, ObjectPrototype*);
+        ObjectConstructor(ExecState*, NonNullPassRefPtr<Structure>, ObjectPrototype*, Structure* prototypeFunctionStructure);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
index 98e47131886b4b85cc9a949999177006679c8335..3065c6d068571a4ab6d74a13fb7a8ea5c2948a2b 100644 (file)
@@ -40,8 +40,9 @@ static JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*, JSObject*,
 static JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue, const ArgList&);
 static JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
 
 static JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue, const ArgList&);
 static JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
 
-ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure)
+ObjectPrototype::ObjectPrototype(ExecState* exec, NonNullPassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure)
     : JSObject(stucture)
     : JSObject(stucture)
+    , m_hasNoPropertiesWithUInt32Names(true)
 {
     putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
     putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
 {
     putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
     putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
@@ -57,6 +58,24 @@ ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<Structure> stucture
     putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum);
 }
 
     putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum);
 }
 
+void ObjectPrototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+{
+    JSObject::put(exec, propertyName, value, slot);
+
+    if (m_hasNoPropertiesWithUInt32Names) {
+        bool isUInt32;
+        propertyName.toStrictUInt32(&isUInt32);
+        m_hasNoPropertiesWithUInt32Names = !isUInt32;
+    }
+}
+
+bool ObjectPrototype::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+    if (m_hasNoPropertiesWithUInt32Names)
+        return false;
+    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
 // ------------------------------ Functions --------------------------------
 
 // ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7
 // ------------------------------ Functions --------------------------------
 
 // ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7
@@ -129,7 +148,7 @@ JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec, JSObject*,
 
 JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 
 JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    return jsNontrivialString(exec, "[object " + thisValue.toThisObject(exec)->className() + "]");
+    return jsNontrivialString(exec, makeString("[object ", thisValue.toThisObject(exec)->className(), "]"));
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 7790ae0909015fe9d898a48cbcb58050508e812f..489d962441b02efba2dc2b6a7839a6d87796d4d2 100644 (file)
@@ -27,7 +27,13 @@ namespace JSC {
 
     class ObjectPrototype : public JSObject {
     public:
 
     class ObjectPrototype : public JSObject {
     public:
-        ObjectPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+        ObjectPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+
+    private:
+        virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+        bool m_hasNoPropertiesWithUInt32Names;
     };
 
     JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
     };
 
     JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
index 093bbecf389cae30a5c128007d44ec14b642900d..0e1887c0f991835a998297b55346dd8bc79bf49c 100644 (file)
 #include <stdio.h>
 #include <wtf/MathExtras.h>
 
 #include <stdio.h>
 #include <wtf/MathExtras.h>
 
-#if HAVE(FLOAT_H)
-#include <float.h>
-#endif
-
 namespace JSC {
 
 bool JSValue::equalSlowCase(ExecState* exec, JSValue v1, JSValue v2)
 namespace JSC {
 
 bool JSValue::equalSlowCase(ExecState* exec, JSValue v1, JSValue v2)
@@ -40,9 +36,9 @@ bool JSValue::equalSlowCase(ExecState* exec, JSValue v1, JSValue v2)
     return equalSlowCaseInline(exec, v1, v2);
 }
 
     return equalSlowCaseInline(exec, v1, v2);
 }
 
-bool JSValue::strictEqualSlowCase(JSValue v1, JSValue v2)
+bool JSValue::strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2)
 {
 {
-    return strictEqualSlowCaseInline(v1, v2);
+    return strictEqualSlowCaseInline(exec, v1, v2);
 }
 
 NEVER_INLINE JSValue throwOutOfMemoryError(ExecState* exec)
 }
 
 NEVER_INLINE JSValue throwOutOfMemoryError(ExecState* exec)
@@ -58,12 +54,13 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
     JSValue p1 = v1.toPrimitive(callFrame);
     JSValue p2 = v2.toPrimitive(callFrame);
 
     JSValue p1 = v1.toPrimitive(callFrame);
     JSValue p2 = v2.toPrimitive(callFrame);
 
-    if (p1.isString() || p2.isString()) {
-        RefPtr<UString::Rep> value = concatenate(p1.toString(callFrame).rep(), p2.toString(callFrame).rep());
-        if (!value)
-            return throwOutOfMemoryError(callFrame);
-        return jsString(callFrame, value.release());
+    if (p1.isString()) {
+        return p2.isString()
+            ? jsString(callFrame, asString(p1), asString(p2))
+            : jsString(callFrame, asString(p1), p2.toString(callFrame));
     }
     }
+    if (p2.isString())
+        return jsString(callFrame, p1.toString(callFrame), asString(p2));
 
     return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame));
 }
 
     return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame));
 }
index f29154da830a27fa3c6b7425f87bcc8a065902f2..c3aa0fa4f65a07302c7577dde378fce739699d94 100644 (file)
@@ -35,6 +35,136 @@ namespace JSC {
     bool jsIsObjectType(JSValue);
     bool jsIsFunctionType(JSValue);
 
     bool jsIsObjectType(JSValue);
     bool jsIsFunctionType(JSValue);
 
+    ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
+    {
+        if (!s1->length())
+            return s2;
+        if (!s2->length())
+            return s1;
+
+        unsigned ropeLength = s1->ropeLength() + s2->ropeLength();
+        JSGlobalData* globalData = &exec->globalData();
+
+        if (ropeLength <= JSString::s_maxInternalRopeLength)
+            return new (globalData) JSString(globalData, ropeLength, s1, s2);
+
+        unsigned index = 0;
+        RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
+        if (UNLIKELY(!rope))
+            return throwOutOfMemoryError(exec);
+        rope->append(index, s1);
+        rope->append(index, s2);
+        ASSERT(index == ropeLength);
+        return new (globalData) JSString(globalData, rope.release());
+    }
+
+    ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, JSString* s2)
+    {
+        unsigned ropeLength = 1 + s2->ropeLength();
+        JSGlobalData* globalData = &exec->globalData();
+
+        if (ropeLength <= JSString::s_maxInternalRopeLength)
+            return new (globalData) JSString(globalData, ropeLength, u1, s2);
+
+        unsigned index = 0;
+        RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
+        if (UNLIKELY(!rope))
+            return throwOutOfMemoryError(exec);
+        rope->append(index, u1);
+        rope->append(index, s2);
+        ASSERT(index == ropeLength);
+        return new (globalData) JSString(globalData, rope.release());
+    }
+
+    ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, const UString& u2)
+    {
+        unsigned ropeLength = s1->ropeLength() + 1;
+        JSGlobalData* globalData = &exec->globalData();
+
+        if (ropeLength <= JSString::s_maxInternalRopeLength)
+            return new (globalData) JSString(globalData, ropeLength, s1, u2);
+
+        unsigned index = 0;
+        RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
+        if (UNLIKELY(!rope))
+            return throwOutOfMemoryError(exec);
+        rope->append(index, s1);
+        rope->append(index, u2);
+        ASSERT(index == ropeLength);
+        return new (globalData) JSString(globalData, rope.release());
+    }
+
+    ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count)
+    {
+        ASSERT(count >= 3);
+
+        unsigned ropeLength = 0;
+        for (unsigned i = 0; i < count; ++i) {
+            JSValue v = strings[i].jsValue();
+            if (LIKELY(v.isString()))
+                ropeLength += asString(v)->ropeLength();
+            else
+                ++ropeLength;
+        }
+
+        JSGlobalData* globalData = &exec->globalData();
+        if (ropeLength == 3)
+            return new (globalData) JSString(exec, strings[0].jsValue(), strings[1].jsValue(), strings[2].jsValue());
+
+        RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
+        if (UNLIKELY(!rope))
+            return throwOutOfMemoryError(exec);
+
+        unsigned index = 0;
+        for (unsigned i = 0; i < count; ++i) {
+            JSValue v = strings[i].jsValue();
+            if (LIKELY(v.isString()))
+                rope->append(index, asString(v));
+            else
+                rope->append(index, v.toString(exec));
+        }
+
+        ASSERT(index == ropeLength);
+        return new (globalData) JSString(globalData, rope.release());
+    }
+
+    ALWAYS_INLINE JSValue jsString(ExecState* exec, JSValue thisValue, const ArgList& args)
+    {
+        unsigned ropeLength = 0;
+        if (LIKELY(thisValue.isString()))
+            ropeLength += asString(thisValue)->ropeLength();
+        else
+            ++ropeLength;
+        for (unsigned i = 0; i < args.size(); ++i) {
+            JSValue v = args.at(i);
+            if (LIKELY(v.isString()))
+                ropeLength += asString(v)->ropeLength();
+            else
+                ++ropeLength;
+        }
+
+        RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
+        if (UNLIKELY(!rope))
+            return throwOutOfMemoryError(exec);
+
+        unsigned index = 0;
+        if (LIKELY(thisValue.isString()))
+            rope->append(index, asString(thisValue));
+        else
+            rope->append(index, thisValue.toString(exec));
+        for (unsigned i = 0; i < args.size(); ++i) {
+            JSValue v = args.at(i);
+            if (LIKELY(v.isString()))
+                rope->append(index, asString(v));
+            else
+                rope->append(index, v.toString(exec));
+        }
+        ASSERT(index == ropeLength);
+
+        JSGlobalData* globalData = &exec->globalData();
+        return new (globalData) JSString(globalData, rope.release());
+    }
+
     // ECMA 11.9.3
     inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2)
     {
     // ECMA 11.9.3
     inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2)
     {
@@ -53,7 +183,7 @@ namespace JSC {
             bool s1 = v1.isString();
             bool s2 = v2.isString();
             if (s1 && s2)
             bool s1 = v1.isString();
             bool s2 = v2.isString();
             if (s1 && s2)
-                return asString(v1)->value() == asString(v2)->value();
+                return asString(v1)->value(exec) == asString(v2)->value(exec);
 
             if (v1.isUndefinedOrNull()) {
                 if (v2.isUndefinedOrNull())
 
             if (v1.isUndefinedOrNull()) {
                 if (v2.isUndefinedOrNull())
@@ -110,17 +240,17 @@ namespace JSC {
     }
 
     // ECMA 11.9.3
     }
 
     // ECMA 11.9.3
-    ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(JSValue v1, JSValue v2)
+    ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
     {
         ASSERT(v1.isCell() && v2.isCell());
 
         if (v1.asCell()->isString() && v2.asCell()->isString())
     {
         ASSERT(v1.isCell() && v2.isCell());
 
         if (v1.asCell()->isString() && v2.asCell()->isString())
-            return asString(v1)->value() == asString(v2)->value();
+            return asString(v1)->value(exec) == asString(v2)->value(exec);
 
         return v1 == v2;
     }
 
 
         return v1 == v2;
     }
 
-    inline bool JSValue::strictEqual(JSValue v1, JSValue v2)
+    inline bool JSValue::strictEqual(ExecState* exec, JSValue v1, JSValue v2)
     {
         if (v1.isInt32() && v2.isInt32())
             return v1 == v2;
     {
         if (v1.isInt32() && v2.isInt32())
             return v1 == v2;
@@ -131,10 +261,10 @@ namespace JSC {
         if (!v1.isCell() || !v2.isCell())
             return v1 == v2;
 
         if (!v1.isCell() || !v2.isCell())
             return v1 == v2;
 
-        return strictEqualSlowCaseInline(v1, v2);
+        return strictEqualSlowCaseInline(exec, v1, v2);
     }
 
     }
 
-    inline bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
+    ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
     {
         if (v1.isInt32() && v2.isInt32())
             return v1.asInt32() < v2.asInt32();
     {
         if (v1.isInt32() && v2.isInt32())
             return v1.asInt32() < v2.asInt32();
@@ -146,7 +276,7 @@ namespace JSC {
 
         JSGlobalData* globalData = &callFrame->globalData();
         if (isJSString(globalData, v1) && isJSString(globalData, v2))
 
         JSGlobalData* globalData = &callFrame->globalData();
         if (isJSString(globalData, v1) && isJSString(globalData, v2))
-            return asString(v1)->value() < asString(v2)->value();
+            return asString(v1)->value(callFrame) < asString(v2)->value(callFrame);
 
         JSValue p1;
         JSValue p2;
 
         JSValue p1;
         JSValue p2;
@@ -156,7 +286,7 @@ namespace JSC {
         if (wasNotString1 | wasNotString2)
             return n1 < n2;
 
         if (wasNotString1 | wasNotString2)
             return n1 < n2;
 
-        return asString(p1)->value() < asString(p2)->value();
+        return asString(p1)->value(callFrame) < asString(p2)->value(callFrame);
     }
 
     inline bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
     }
 
     inline bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
@@ -171,7 +301,7 @@ namespace JSC {
 
         JSGlobalData* globalData = &callFrame->globalData();
         if (isJSString(globalData, v1) && isJSString(globalData, v2))
 
         JSGlobalData* globalData = &callFrame->globalData();
         if (isJSString(globalData, v1) && isJSString(globalData, v2))
-            return !(asString(v2)->value() < asString(v1)->value());
+            return !(asString(v2)->value(callFrame) < asString(v1)->value(callFrame));
 
         JSValue p1;
         JSValue p2;
 
         JSValue p1;
         JSValue p2;
@@ -181,7 +311,7 @@ namespace JSC {
         if (wasNotString1 | wasNotString2)
             return n1 <= n2;
 
         if (wasNotString1 | wasNotString2)
             return n1 <= n2;
 
-        return !(asString(p2)->value() < asString(p1)->value());
+        return !(asString(p2)->value(callFrame) < asString(p1)->value(callFrame));
     }
 
     // Fast-path choices here are based on frequency data from SunSpider:
     }
 
     // Fast-path choices here are based on frequency data from SunSpider:
@@ -195,29 +325,14 @@ namespace JSC {
 
     ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
     {
 
     ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
     {
-        double left;
-        double right = 0.0;
-
-        bool rightIsNumber = v2.getNumber(right);
-        if (rightIsNumber && v1.getNumber(left))
+        double left = 0.0, right;
+        if (v1.getNumber(left) && v2.getNumber(right))
             return jsNumber(callFrame, left + right);
         
             return jsNumber(callFrame, left + right);
         
-        bool leftIsString = v1.isString();
-        if (leftIsString && v2.isString()) {
-            RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep());
-            if (!value)
-                return throwOutOfMemoryError(callFrame);
-            return jsString(callFrame, value.release());
-        }
-
-        if (rightIsNumber & leftIsString) {
-            RefPtr<UString::Rep> value = v2.isInt32() ?
-                concatenate(asString(v1)->value().rep(), v2.asInt32()) :
-                concatenate(asString(v1)->value().rep(), right);
-
-            if (!value)
-                return throwOutOfMemoryError(callFrame);
-            return jsString(callFrame, value.release());
+        if (v1.isString()) {
+            return v2.isString()
+                ? jsString(callFrame, asString(v1), asString(v2))
+                : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
         }
 
         // All other cases are pretty uncommon
         }
 
         // All other cases are pretty uncommon
@@ -255,6 +370,25 @@ namespace JSC {
         return count;
     }
 
         return count;
     }
 
+    inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base)
+    {
+        size_t count = 0;
+        while (1) {
+            JSValue v = base->structure()->prototypeForLookup(callFrame);
+            if (v.isNull())
+                return count;
+
+            base = asCell(v);
+
+            // Since we're accessing a prototype in a loop, it's a good bet that it
+            // should not be treated as a dictionary.
+            if (base->structure()->isDictionary())
+                asObject(base)->flattenDictionaryObject();
+
+            ++count;
+        }
+    }
+
     ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain)
     {
         ScopeChainIterator iter = scopeChain->begin();
     ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain)
     {
         ScopeChainIterator iter = scopeChain->begin();
@@ -277,59 +411,6 @@ namespace JSC {
         ASSERT_NOT_REACHED();
         return JSValue();
     }
         ASSERT_NOT_REACHED();
         return JSValue();
     }
-
-    ALWAYS_INLINE JSValue concatenateStrings(CallFrame* callFrame, Register* strings, unsigned count)
-    {
-        ASSERT(count >= 3);
-
-        // Estimate the amount of space required to hold the entire string.  If all
-        // arguments are strings, we can easily calculate the exact amount of space
-        // required.  For any other arguments, for now let's assume they may require
-        // 11 UChars of storage.  This is enouch to hold any int, and likely is also
-        // reasonable for the other immediates.  We may want to come back and tune
-        // this value at some point.
-        unsigned bufferSize = 0;
-        for (unsigned i = 0; i < count; ++i) {
-            JSValue v = strings[i].jsValue();
-            if (LIKELY(v.isString()))
-                bufferSize += asString(v)->value().size();
-            else
-                bufferSize += 11;
-        }
-
-        // Allocate an output string to store the result.
-        // If the first argument is a String, and if it has the capacity (or can grow
-        // its capacity) to hold the entire result then use this as a base to concatenate
-        // onto.  Otherwise, allocate a new empty output buffer.
-        JSValue firstValue = strings[0].jsValue();
-        RefPtr<UString::Rep> resultRep;
-        if (firstValue.isString() && (resultRep = asString(firstValue)->value().rep())->reserveCapacity(bufferSize)) {
-            // We're going to concatenate onto the first string - remove it from the list of items to be appended.
-            ++strings;
-            --count;
-        } else
-            resultRep = UString::Rep::createEmptyBuffer(bufferSize);
-        UString result(resultRep);
-
-        // Loop over the openards, writing them into the output buffer.
-        for (unsigned i = 0; i < count; ++i) {
-            JSValue v = strings[i].jsValue();
-            if (LIKELY(v.isString()))
-                result.append(asString(v)->value());
-            else if (v.isInt32())
-                result.appendNumeric(v.asInt32());
-            else {
-                double d;
-                if (v.getNumber(d))
-                    result.appendNumeric(d);
-                else
-                    result.append(v.toString(callFrame));
-            }
-        }
-
-        return jsString(callFrame, result);
-    }
-
 } // namespace JSC
 
 #endif // Operations_h
 } // namespace JSC
 
 #endif // Operations_h
diff --git a/runtime/PropertyDescriptor.cpp b/runtime/PropertyDescriptor.cpp
new file mode 100644 (file)
index 0000000..558ae28
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+
+#include "config.h"
+
+#include "PropertyDescriptor.h"
+
+#include "GetterSetter.h"
+#include "JSObject.h"
+#include "Operations.h"
+
+namespace JSC {
+unsigned PropertyDescriptor::defaultAttributes = (DontDelete << 1) - 1;
+
+bool PropertyDescriptor::writable() const
+{
+    ASSERT(!isAccessorDescriptor());
+    return !(m_attributes & ReadOnly);
+}
+
+bool PropertyDescriptor::enumerable() const
+{
+    return !(m_attributes & DontEnum);
+}
+
+bool PropertyDescriptor::configurable() const
+{
+    return !(m_attributes & DontDelete);
+}
+
+bool PropertyDescriptor::isDataDescriptor() const
+{
+    return m_value || (m_seenAttributes & WritablePresent);
+}
+
+bool PropertyDescriptor::isGenericDescriptor() const
+{
+    return !isAccessorDescriptor() && !isDataDescriptor();
+}
+
+bool PropertyDescriptor::isAccessorDescriptor() const
+{
+    return m_getter || m_setter;
+}
+
+void PropertyDescriptor::setUndefined()
+{
+    m_value = jsUndefined();
+    m_attributes = ReadOnly | DontDelete | DontEnum;
+}
+
+JSValue PropertyDescriptor::getter() const
+{
+    ASSERT(isAccessorDescriptor());
+    return m_getter;
+}
+
+JSValue PropertyDescriptor::setter() const
+{
+    ASSERT(isAccessorDescriptor());
+    return m_setter;
+}
+
+void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
+{
+    ASSERT(value);
+    m_attributes = attributes;
+    if (attributes & (Getter | Setter)) {
+        GetterSetter* accessor = asGetterSetter(value);
+        m_getter = accessor->getter();
+        m_setter = accessor->setter();
+        ASSERT(m_getter || m_setter);
+        m_seenAttributes = EnumerablePresent | ConfigurablePresent;
+        m_attributes &= ~ReadOnly;
+    } else {
+        m_value = value;
+        m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent;
+    }
+}
+
+void PropertyDescriptor::setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes)
+{
+    ASSERT(attributes & (Getter | Setter));
+    ASSERT(getter || setter);
+    m_attributes = attributes;
+    m_getter = getter;
+    m_setter = setter;
+    m_attributes &= ~ReadOnly;
+    m_seenAttributes = EnumerablePresent | ConfigurablePresent;
+}
+
+void PropertyDescriptor::setWritable(bool writable)
+{
+    if (writable)
+        m_attributes &= ~ReadOnly;
+    else
+        m_attributes |= ReadOnly;
+    m_seenAttributes |= WritablePresent;
+}
+
+void PropertyDescriptor::setEnumerable(bool enumerable)
+{
+    if (enumerable)
+        m_attributes &= ~DontEnum;
+    else
+        m_attributes |= DontEnum;
+    m_seenAttributes |= EnumerablePresent;
+}
+
+void PropertyDescriptor::setConfigurable(bool configurable)
+{
+    if (configurable)
+        m_attributes &= ~DontDelete;
+    else
+        m_attributes |= DontDelete;
+    m_seenAttributes |= ConfigurablePresent;
+}
+
+void PropertyDescriptor::setSetter(JSValue setter)
+{
+    m_setter = setter;
+    m_attributes |= Setter;
+    m_attributes &= ~ReadOnly;
+}
+
+void PropertyDescriptor::setGetter(JSValue getter)
+{
+    m_getter = getter;
+    m_attributes |= Getter;
+    m_attributes &= ~ReadOnly;
+}
+
+bool PropertyDescriptor::equalTo(ExecState* exec, const PropertyDescriptor& other) const
+{
+    if (!other.m_value == m_value ||
+        !other.m_getter == m_getter ||
+        !other.m_setter == m_setter)
+        return false;
+    return (!m_value || JSValue::strictEqual(exec, other.m_value, m_value)) && 
+           (!m_getter || JSValue::strictEqual(exec, other.m_getter, m_getter)) && 
+           (!m_setter || JSValue::strictEqual(exec, other.m_setter, m_setter)) &&
+           attributesEqual(other);
+}
+
+bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
+{
+    unsigned mismatch = other.m_attributes ^ m_attributes;
+    unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
+    if (sharedSeen & WritablePresent && mismatch & ReadOnly)
+        return false;
+    if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
+        return false;
+    if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
+        return false;
+    return true;
+}
+
+unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& other) const
+{
+    unsigned mismatch = other.m_attributes ^ m_attributes;
+    unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
+    unsigned newAttributes = m_attributes & defaultAttributes;
+    if (sharedSeen & WritablePresent && mismatch & ReadOnly)
+        newAttributes ^= ReadOnly;
+    if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
+        newAttributes ^= DontDelete;
+    if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
+        newAttributes ^= DontEnum;
+    return newAttributes;
+}
+
+}
diff --git a/runtime/PropertyDescriptor.h b/runtime/PropertyDescriptor.h
new file mode 100644 (file)
index 0000000..ff9f160
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PropertyDescriptor_h
+#define PropertyDescriptor_h
+
+#include "JSValue.h"
+
+namespace JSC {
+    class PropertyDescriptor {
+    public:
+        PropertyDescriptor()
+            : m_attributes(defaultAttributes)
+            , m_seenAttributes(0)
+        {
+        }
+        bool writable() const;
+        bool enumerable() const;
+        bool configurable() const;
+        bool isDataDescriptor() const;
+        bool isGenericDescriptor() const;
+        bool isAccessorDescriptor() const;
+        unsigned attributes() const { return m_attributes; }
+        JSValue value() const { return m_value; }
+        JSValue getter() const;
+        JSValue setter() const;
+        void setUndefined();
+        void setDescriptor(JSValue value, unsigned attributes);
+        void setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes);
+        void setWritable(bool);
+        void setEnumerable(bool);
+        void setConfigurable(bool);
+        void setValue(JSValue value) { m_value = value; }
+        void setSetter(JSValue);
+        void setGetter(JSValue);
+        bool isEmpty() const { return !(m_value || m_getter || m_setter || m_seenAttributes); }
+        bool writablePresent() const { return m_seenAttributes & WritablePresent; }
+        bool enumerablePresent() const { return m_seenAttributes & EnumerablePresent; }
+        bool configurablePresent() const { return m_seenAttributes & ConfigurablePresent; }
+        bool setterPresent() const { return m_setter; }
+        bool getterPresent() const { return m_getter; }
+        bool equalTo(ExecState* exec, const PropertyDescriptor& other) const;
+        bool attributesEqual(const PropertyDescriptor& other) const;
+        unsigned attributesWithOverride(const PropertyDescriptor& other) const;
+    private:
+        static unsigned defaultAttributes;
+        bool operator==(const PropertyDescriptor&){ return false; }
+        enum { WritablePresent = 1, EnumerablePresent = 2, ConfigurablePresent = 4};
+        // May be a getter/setter
+        JSValue m_value;
+        JSValue m_getter;
+        JSValue m_setter;
+        unsigned m_attributes;
+        unsigned m_seenAttributes;
+    };
+}
+
+#endif
index 0878e73f879da6b0923227fbc5d488d922bcdff5..5108272fd398152024933b2281e2562074808781 100644 (file)
 #include "config.h"
 #include "PropertyNameArray.h"
 
 #include "config.h"
 #include "PropertyNameArray.h"
 
+#include "Structure.h"
+#include "StructureChain.h"
+
 namespace JSC {
 
 static const size_t setThreshold = 20;
 
 void PropertyNameArray::add(UString::Rep* identifier)
 {
 namespace JSC {
 
 static const size_t setThreshold = 20;
 
 void PropertyNameArray::add(UString::Rep* identifier)
 {
-    ASSERT(identifier == &UString::Rep::null() || identifier == &UString::Rep::empty() || identifier->identifierTable());
+    ASSERT(identifier == &UString::Rep::null() || identifier == &UString::Rep::empty() || identifier->isIdentifier());
 
     size_t size = m_data->propertyNameVector().size();
     if (size < setThreshold) {
 
     size_t size = m_data->propertyNameVector().size();
     if (size < setThreshold) {
@@ -44,7 +47,7 @@ void PropertyNameArray::add(UString::Rep* identifier)
             return;
     }
 
             return;
     }
 
-    m_data->propertyNameVector().append(Identifier(m_globalData, identifier));
+    addKnownUnique(identifier);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index b4382f4228d9cb92ced635ef7925089a71c84a73..3dbcc9df746ffaa1f8e6f760a5dc072ca44d391c 100644 (file)
 
 #include "CallFrame.h"
 #include "Identifier.h"
 
 #include "CallFrame.h"
 #include "Identifier.h"
-#include "Structure.h"
 #include <wtf/HashSet.h>
 #include <wtf/HashSet.h>
+#include <wtf/OwnArrayPtr.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
 #include <wtf/Vector.h>
 
 namespace JSC {
+    
+    class Structure;
+    class StructureChain;
 
 
+    // FIXME: Rename to PropertyNameArray.
     class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> {
     public:
         typedef Vector<Identifier, 20> PropertyNameVector;
     class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> {
     public:
         typedef Vector<Identifier, 20> PropertyNameVector;
-        typedef PropertyNameVector::const_iterator const_iterator;
 
         static PassRefPtr<PropertyNameArrayData> create() { return adoptRef(new PropertyNameArrayData); }
 
 
         static PassRefPtr<PropertyNameArrayData> create() { return adoptRef(new PropertyNameArrayData); }
 
-        const_iterator begin() const { return m_propertyNameVector.begin(); }
-        const_iterator end() const { return m_propertyNameVector.end(); }
-
         PropertyNameVector& propertyNameVector() { return m_propertyNameVector; }
 
         PropertyNameVector& propertyNameVector() { return m_propertyNameVector; }
 
-        void setCachedStructure(Structure* structure) { m_cachedStructure = structure; }
-        Structure* cachedStructure() const { return m_cachedStructure; }
-
-        void setCachedPrototypeChain(PassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
-        StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
-
     private:
         PropertyNameArrayData()
     private:
         PropertyNameArrayData()
-            : m_cachedStructure(0)
         {
         }
 
         PropertyNameVector m_propertyNameVector;
         {
         }
 
         PropertyNameVector m_propertyNameVector;
-        Structure* m_cachedStructure;
-        RefPtr<StructureChain> m_cachedPrototypeChain;
     };
 
     };
 
+    // FIXME: Rename to PropertyNameArrayBuilder.
     class PropertyNameArray {
     public:
     class PropertyNameArray {
     public:
-        typedef PropertyNameArrayData::const_iterator const_iterator;
-
         PropertyNameArray(JSGlobalData* globalData)
             : m_data(PropertyNameArrayData::create())
             , m_globalData(globalData)
         PropertyNameArray(JSGlobalData* globalData)
             : m_data(PropertyNameArrayData::create())
             , m_globalData(globalData)
@@ -82,21 +72,18 @@ namespace JSC {
         void add(UString::Rep*);
         void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
 
         void add(UString::Rep*);
         void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
 
-        size_t size() const { return m_data->propertyNameVector().size(); }
-
         Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
         const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
 
         Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
         const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
 
-        const_iterator begin() const { return m_data->begin(); }
-        const_iterator end() const { return m_data->end(); }
-
         void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; }
         PropertyNameArrayData* data() { return m_data.get(); }
         void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; }
         PropertyNameArrayData* data() { return m_data.get(); }
-
         PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); }
 
         PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); }
 
-        void setShouldCache(bool shouldCache) { m_shouldCache = shouldCache; }
-        bool shouldCache() const { return m_shouldCache; }
+        // FIXME: Remove these functions.
+        typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator;
+        size_t size() const { return m_data->propertyNameVector().size(); }
+        const_iterator begin() const { return m_data->propertyNameVector().begin(); }
+        const_iterator end() const { return m_data->propertyNameVector().end(); }
 
     private:
         typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet;
 
     private:
         typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet;
index 36fa5d83d6102e29c2a2f15bd4c454c92075da2c..a0a2f48f9c5c1d9334ec4c88eae3702cf17152ca 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
-#include "JSObject.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -39,7 +38,7 @@ JSValue PropertySlot::functionGetter(ExecState* exec, const Identifier&, const P
         return callData.native.function(exec, slot.m_data.getterFunc, slot.slotBase(), exec->emptyList());
     ASSERT(callType == CallTypeJS);
     // FIXME: Can this be done more efficiently using the callData?
         return callData.native.function(exec, slot.m_data.getterFunc, slot.slotBase(), exec->emptyList());
     ASSERT(callType == CallTypeJS);
     // FIXME: Can this be done more efficiently using the callData?
-    return static_cast<JSFunction*>(slot.m_data.getterFunc)->call(exec, slot.slotBase(), exec->emptyList());
+    return asFunction(slot.m_data.getterFunc)->call(exec, slot.slotBase(), exec->emptyList());
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 224164d2f91b1bbad066e7087974b994a5b28e3c..a0d5443dce723923e09c0c524a5231dae9b9c709 100644 (file)
@@ -22,8 +22,8 @@
 #ifndef Protect_h
 #define Protect_h
 
 #ifndef Protect_h
 #define Protect_h
 
-#include "JSCell.h"
 #include "Collector.h"
 #include "Collector.h"
+#include "JSValue.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
index 8e3d107835f27bf7ca4c73b4c7f160e6496df51a..38f8adbbbd0eeaece442beacdb92b7238117810c 100644 (file)
@@ -40,7 +40,7 @@ PrototypeFunction::PrototypeFunction(ExecState* exec, int length, const Identifi
     putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
 }
 
     putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
 }
 
-PrototypeFunction::PrototypeFunction(ExecState* exec, PassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function)
+PrototypeFunction::PrototypeFunction(ExecState* exec, NonNullPassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function)
     : InternalFunction(&exec->globalData(), prototypeFunctionStructure, name)
     , m_function(function)
 {
     : InternalFunction(&exec->globalData(), prototypeFunctionStructure, name)
     , m_function(function)
 {
index 99ab3279842f953e69b42f65efb8e58a005b8bd9..70ee034f1f8f0b8e0a246d11cede84a2b3870adc 100644 (file)
@@ -32,7 +32,7 @@ namespace JSC {
     class PrototypeFunction : public InternalFunction {
     public:
         PrototypeFunction(ExecState*, int length, const Identifier&, NativeFunction);
     class PrototypeFunction : public InternalFunction {
     public:
         PrototypeFunction(ExecState*, int length, const Identifier&, NativeFunction);
-        PrototypeFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
+        PrototypeFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
 
     private:
         virtual CallType getCallData(CallData&);
 
     private:
         virtual CallType getCallData(CallData&);
index 7dd4a8ffdede0b04eead102d02bffca35b2eb10f..4e958f49d5943127e1e9ed58f29713cf07101358 100644 (file)
@@ -65,7 +65,6 @@ inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern)
 
 inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
     : m_pattern(pattern)
 
 inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
     : m_pattern(pattern)
-    , m_flags(flags)
     , m_flagBits(0)
     , m_constructionError(0)
     , m_numSubpatterns(0)
     , m_flagBits(0)
     , m_constructionError(0)
     , m_numSubpatterns(0)
index 24d4199f4c7478985cd7d3780736982708714d01..61ab0bc284d17a15242936fbe3969b3a2b26f0be 100644 (file)
@@ -49,7 +49,6 @@ namespace JSC {
         bool multiline() const { return m_flagBits & Multiline; }
 
         const UString& pattern() const { return m_pattern; }
         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; }
 
         bool isValid() const { return !m_constructionError; }
         const char* errorMessage() const { return m_constructionError; }
@@ -66,7 +65,6 @@ namespace JSC {
         enum FlagBits { Global = 1, IgnoreCase = 2, Multiline = 4 };
 
         UString m_pattern; // FIXME: Just decompile m_regExp instead of storing this.
         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;
         const char* m_constructionError;
         unsigned m_numSubpatterns;
         int m_flagBits;
         const char* m_constructionError;
         unsigned m_numSubpatterns;
index e46852130ebc0b84bf938aaa12c6b3c25f036688..6f001429200cedb40264fc0448d701dec7209b4f 100644 (file)
@@ -23,6 +23,7 @@
 #include "RegExpConstructor.h"
 
 #include "ArrayPrototype.h"
 #include "RegExpConstructor.h"
 
 #include "ArrayPrototype.h"
+#include "Error.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JSString.h"
@@ -89,29 +90,7 @@ const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info,
 @end
 */
 
 @end
 */
 
-struct RegExpConstructorPrivate {
-    // Global search cache / settings
-    RegExpConstructorPrivate()
-        : lastNumSubPatterns(0)
-        , multiline(false)
-        , lastOvectorIndex(0)
-    {
-    }
-
-    const Vector<int, 32>& lastOvector() const { return ovector[lastOvectorIndex]; }
-    Vector<int, 32>& lastOvector() { return ovector[lastOvectorIndex]; }
-    Vector<int, 32>& tempOvector() { return ovector[lastOvectorIndex ? 0 : 1]; }
-    void changeLastOvector() { lastOvectorIndex = lastOvectorIndex ? 0 : 1; }
-
-    UString input;
-    UString lastInput;
-    Vector<int, 32> ovector[2];
-    unsigned lastNumSubPatterns : 30;
-    bool multiline : 1;
-    unsigned lastOvectorIndex : 1;
-};
-
-RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
+RegExpConstructor::RegExpConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, "RegExp"))
     , d(new RegExpConstructorPrivate)
 {
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, "RegExp"))
     , d(new RegExpConstructorPrivate)
 {
@@ -122,30 +101,6 @@ RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<Structure> stru
     putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly | DontDelete | DontEnum);
 }
 
     putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly | DontDelete | DontEnum);
 }
 
-/* 
-  To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular
-  expression matching through the performMatch function. We use cached results to calculate, 
-  e.g., RegExp.lastMatch and RegExp.leftParen.
-*/
-void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
-{
-    position = r->match(s, startOffset, &d->tempOvector());
-
-    if (ovector)
-        *ovector = d->tempOvector().data();
-
-    if (position != -1) {
-        ASSERT(!d->tempOvector().isEmpty());
-
-        length = d->tempOvector()[1] - d->tempOvector()[0];
-
-        d->input = s;
-        d->lastInput = s;
-        d->changeLastOvector();
-        d->lastNumSubPatterns = r->numSubpatterns();
-    }
-}
-
 RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data)
     : JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1)
 {
 RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data)
     : JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1)
 {
@@ -177,6 +132,8 @@ void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
         int start = d->lastOvector()[2 * i];
         if (start >= 0)
             JSArray::put(exec, i, jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start));
         int start = d->lastOvector()[2 * i];
         if (start >= 0)
             JSArray::put(exec, i, jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start));
+        else
+            JSArray::put(exec, i, jsUndefined());
     }
 
     PutPropertySlot slot;
     }
 
     PutPropertySlot slot;
@@ -233,6 +190,11 @@ bool RegExpConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& pr
     return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot);
 }
 
     return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot);
 }
 
+bool RegExpConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticValueDescriptor<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, descriptor);
+}
+
 JSValue regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot)
 {
     return asRegExpConstructor(slot.slotBase())->getBackref(exec, 1);
 JSValue regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot)
 {
     return asRegExpConstructor(slot.slotBase())->getBackref(exec, 1);
@@ -329,7 +291,7 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args)
     JSValue arg0 = args.at(0);
     JSValue arg1 = args.at(1);
 
     JSValue arg0 = args.at(0);
     JSValue arg1 = args.at(1);
 
-    if (arg0.isObject(&RegExpObject::info)) {
+    if (arg0.inherits(&RegExpObject::info)) {
         if (!arg1.isUndefined())
             return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
         return asObject(arg0);
         if (!arg1.isUndefined())
             return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
         return asObject(arg0);
@@ -340,7 +302,7 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args)
 
     RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags);
     if (!regExp->isValid())
 
     RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags);
     if (!regExp->isValid())
-        return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
+        return throwError(exec, SyntaxError, makeString("Invalid regular expression: ", regExp->errorMessage()));
     return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
 }
 
     return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
 }
 
index 6823f3fb709801be9300064eb40a8ec7adf3821b..8f4be71687a0f3177738060bcdbb9bcea02fca65 100644 (file)
@@ -22,6 +22,7 @@
 #define RegExpConstructor_h
 
 #include "InternalFunction.h"
 #define RegExpConstructor_h
 
 #include "InternalFunction.h"
+#include "RegExp.h"
 #include <wtf/OwnPtr.h>
 
 namespace JSC {
 #include <wtf/OwnPtr.h>
 
 namespace JSC {
@@ -30,17 +31,40 @@ namespace JSC {
     class RegExpPrototype;
     struct RegExpConstructorPrivate;
 
     class RegExpPrototype;
     struct RegExpConstructorPrivate;
 
+    struct RegExpConstructorPrivate : FastAllocBase {
+        // Global search cache / settings
+        RegExpConstructorPrivate()
+            : lastNumSubPatterns(0)
+            , multiline(false)
+            , lastOvectorIndex(0)
+        {
+        }
+
+        const Vector<int, 32>& lastOvector() const { return ovector[lastOvectorIndex]; }
+        Vector<int, 32>& lastOvector() { return ovector[lastOvectorIndex]; }
+        Vector<int, 32>& tempOvector() { return ovector[lastOvectorIndex ? 0 : 1]; }
+        void changeLastOvector() { lastOvectorIndex = lastOvectorIndex ? 0 : 1; }
+
+        UString input;
+        UString lastInput;
+        Vector<int, 32> ovector[2];
+        unsigned lastNumSubPatterns : 30;
+        bool multiline : 1;
+        unsigned lastOvectorIndex : 1;
+    };
+
     class RegExpConstructor : public InternalFunction {
     public:
     class RegExpConstructor : public InternalFunction {
     public:
-        RegExpConstructor(ExecState*, PassRefPtr<Structure>, RegExpPrototype*);
+        RegExpConstructor(ExecState*, NonNullPassRefPtr<Structure>, RegExpPrototype*);
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
 
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         }
 
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         static const ClassInfo info;
 
 
         static const ClassInfo info;
 
@@ -58,6 +82,9 @@ namespace JSC {
         JSValue getLeftContext(ExecState*) const;
         JSValue getRightContext(ExecState*) const;
 
         JSValue getLeftContext(ExecState*) const;
         JSValue getRightContext(ExecState*) const;
 
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | InternalFunction::StructureFlags;
+
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
@@ -77,6 +104,30 @@ namespace JSC {
         return static_cast<RegExpConstructor*>(asObject(value));
     }
 
         return static_cast<RegExpConstructor*>(asObject(value));
     }
 
+    /* 
+      To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular
+      expression matching through the performMatch function. We use cached results to calculate, 
+      e.g., RegExp.lastMatch and RegExp.leftParen.
+    */
+    inline void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
+    {
+        position = r->match(s, startOffset, &d->tempOvector());
+
+        if (ovector)
+            *ovector = d->tempOvector().data();
+
+        if (position != -1) {
+            ASSERT(!d->tempOvector().isEmpty());
+
+            length = d->tempOvector()[1] - d->tempOvector()[0];
+
+            d->input = s;
+            d->lastInput = s;
+            d->changeLastOvector();
+            d->lastNumSubPatterns = r->numSubpatterns();
+        }
+    }
+
 } // namespace JSC
 
 #endif // RegExpConstructor_h
 } // namespace JSC
 
 #endif // RegExpConstructor_h
index 9ae18b9e891492460c8b6491bf568e637c4c1bcd..38d3cb4495733d3cd9e0bba2fcdb187f87e33356 100644 (file)
@@ -44,6 +44,13 @@ namespace JSC {
             return JSArray::getOwnPropertySlot(exec, propertyName, slot);
         }
 
             return JSArray::getOwnPropertySlot(exec, propertyName, slot);
         }
 
+        virtual bool getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+        {
+            if (lazyCreationData())
+                fillArrayInstance(exec);
+            return JSArray::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+        }
+
         virtual void put(ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot)
         {
             if (lazyCreationData())
         virtual void put(ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot)
         {
             if (lazyCreationData())
@@ -72,11 +79,11 @@ namespace JSC {
             return JSArray::deleteProperty(exec, propertyName);
         }
 
             return JSArray::deleteProperty(exec, propertyName);
         }
 
-        virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr)
+        virtual void getOwnPropertyNames(ExecState* exec, PropertyNameArray& arr, EnumerationMode mode = ExcludeDontEnumProperties)
         {
             if (lazyCreationData())
                 fillArrayInstance(exec);
         {
             if (lazyCreationData())
                 fillArrayInstance(exec);
-            JSArray::getPropertyNames(exec, arr);
+            JSArray::getOwnPropertyNames(exec, arr, mode);
         }
 
         void fillArrayInstance(ExecState*);
         }
 
         void fillArrayInstance(ExecState*);
index 687844ed5213ced3a98be4d03f1fbb6ff3204cbc..42bfceffbc9c705ed0caae23be2e0c42c73c27eb 100644 (file)
@@ -57,7 +57,7 @@ const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
 @end
 */
 
 @end
 */
 
-RegExpObject::RegExpObject(PassRefPtr<Structure> structure, PassRefPtr<RegExp> regExp)
+RegExpObject::RegExpObject(NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<RegExp> regExp)
     : JSObject(structure)
     , d(new RegExpObjectData(regExp, 0))
 {
     : JSObject(structure)
     , d(new RegExpObjectData(regExp, 0))
 {
@@ -72,6 +72,11 @@ bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propert
     return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
 }
 
     return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
 }
 
+bool RegExpObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, descriptor);
+}
+
 JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot)
 {
     return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global());
 JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot)
 {
     return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global());
@@ -137,7 +142,7 @@ bool RegExpObject::match(ExecState* exec, const ArgList& args)
 
     UString input = args.isEmpty() ? regExpConstructor->input() : args.at(0).toString(exec);
     if (input.isNull()) {
 
     UString input = args.isEmpty() ? regExpConstructor->input() : args.at(0).toString(exec);
     if (input.isNull()) {
-        throwError(exec, GeneralError, "No input to " + toString(exec) + ".");
+        throwError(exec, GeneralError, makeString("No input to ", toString(exec), "."));
         return false;
     }
 
         return false;
     }
 
@@ -154,7 +159,7 @@ bool RegExpObject::match(ExecState* exec, const ArgList& args)
     }
 
     int position;
     }
 
     int position;
-    int length;
+    int length = 0;
     regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length);
     if (position < 0) {
         d->lastIndex = 0;
     regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length);
     if (position < 0) {
         d->lastIndex = 0;
index fac9978f10a46977e3ab11c382624017ff0f33b4..4ad11ef7a5907264b281b850fef1a62e3ac6ee12 100644 (file)
@@ -28,7 +28,7 @@ namespace JSC {
 
     class RegExpObject : public JSObject {
     public:
 
     class RegExpObject : public JSObject {
     public:
-        RegExpObject(PassRefPtr<Structure>, PassRefPtr<RegExp>);
+        RegExpObject(NonNullPassRefPtr<Structure>, NonNullPassRefPtr<RegExp>);
         virtual ~RegExpObject();
 
         void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; }
         virtual ~RegExpObject();
 
         void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; }
@@ -41,6 +41,7 @@ namespace JSC {
         JSValue exec(ExecState*, const ArgList&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         JSValue exec(ExecState*, const ArgList&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
 
         virtual const ClassInfo* classInfo() const { return &info; }
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
 
         virtual const ClassInfo* classInfo() const { return &info; }
@@ -48,16 +49,19 @@ namespace JSC {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType));
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
 
         }
 
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
+
     private:
         bool match(ExecState*, const ArgList&);
 
         virtual CallType getCallData(CallData&);
 
     private:
         bool match(ExecState*, const ArgList&);
 
         virtual CallType getCallData(CallData&);
 
-        struct RegExpObjectData {
-            RegExpObjectData(PassRefPtr<RegExp> regExp, double lastIndex)
+        struct RegExpObjectData : FastAllocBase {
+            RegExpObjectData(NonNullPassRefPtr<RegExp> regExp, double lastIndex)
                 : regExp(regExp)
                 , lastIndex(lastIndex)
             {
                 : regExp(regExp)
                 , lastIndex(lastIndex)
             {
index b1ab889e04cc27cdcb6cf590367110fc436f699f..5f9d3575e98e0ec7060c80b0bc45c010cb73aaaf 100644 (file)
@@ -22,6 +22,7 @@
 #include "RegExpPrototype.h"
 
 #include "ArrayPrototype.h"
 #include "RegExpPrototype.h"
 
 #include "ArrayPrototype.h"
+#include "Error.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JSObject.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JSObject.h"
@@ -45,7 +46,7 @@ static JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*, JSObject*, JSVa
 
 const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 };
 
 
 const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 };
 
-RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+RegExpPrototype::RegExpPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
     : JSObject(structure)
 {
     putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
     : JSObject(structure)
 {
     putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
@@ -58,28 +59,28 @@ RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<Structure> structur
     
 JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
     
 JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
-    if (!thisValue.isObject(&RegExpObject::info))
+    if (!thisValue.inherits(&RegExpObject::info))
         return throwError(exec, TypeError);
     return asRegExpObject(thisValue)->test(exec, args);
 }
 
 JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
         return throwError(exec, TypeError);
     return asRegExpObject(thisValue)->test(exec, args);
 }
 
 JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
-    if (!thisValue.isObject(&RegExpObject::info))
+    if (!thisValue.inherits(&RegExpObject::info))
         return throwError(exec, TypeError);
     return asRegExpObject(thisValue)->exec(exec, args);
 }
 
 JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
         return throwError(exec, TypeError);
     return asRegExpObject(thisValue)->exec(exec, args);
 }
 
 JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
-    if (!thisValue.isObject(&RegExpObject::info))
+    if (!thisValue.inherits(&RegExpObject::info))
         return throwError(exec, TypeError);
 
     RefPtr<RegExp> regExp;
     JSValue arg0 = args.at(0);
     JSValue arg1 = args.at(1);
     
         return throwError(exec, TypeError);
 
     RefPtr<RegExp> regExp;
     JSValue arg0 = args.at(0);
     JSValue arg1 = args.at(1);
     
-    if (arg0.isObject(&RegExpObject::info)) {
+    if (arg0.inherits(&RegExpObject::info)) {
         if (!arg1.isUndefined())
             return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
         regExp = asRegExpObject(arg0)->regExp();
         if (!arg1.isUndefined())
             return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
         regExp = asRegExpObject(arg0)->regExp();
@@ -90,7 +91,7 @@ JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue
     }
 
     if (!regExp->isValid())
     }
 
     if (!regExp->isValid())
-        return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
+        return throwError(exec, SyntaxError, makeString("Invalid regular expression: ", regExp->errorMessage()));
 
     asRegExpObject(thisValue)->setRegExp(regExp.release());
     asRegExpObject(thisValue)->setLastIndex(0);
 
     asRegExpObject(thisValue)->setRegExp(regExp.release());
     asRegExpObject(thisValue)->setLastIndex(0);
@@ -99,21 +100,23 @@ JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue
 
 JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
 
 JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
-    if (!thisValue.isObject(&RegExpObject::info)) {
-        if (thisValue.isObject(&RegExpPrototype::info))
+    if (!thisValue.inherits(&RegExpObject::info)) {
+        if (thisValue.inherits(&RegExpPrototype::info))
             return jsNontrivialString(exec, "//");
         return throwError(exec, TypeError);
     }
 
             return jsNontrivialString(exec, "//");
         return throwError(exec, TypeError);
     }
 
-    UString result = "/" + asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec);
-    result.append('/');
+    char postfix[5] = { '/', 0, 0, 0, 0 };
+    int index = 1;
     if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global).toBoolean(exec))
     if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global).toBoolean(exec))
-        result.append('g');
+        postfix[index++] = 'g';
     if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec))
     if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec))
-        result.append('i');
+        postfix[index++] = 'i';
     if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline).toBoolean(exec))
     if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline).toBoolean(exec))
-        result.append('m');
-    return jsNontrivialString(exec, result);
+        postfix[index] = 'm';
+    UString source = asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec);
+    // If source is empty, use "/(?:)/" to avoid colliding with comment syntax
+    return jsNontrivialString(exec, makeString("/", source.size() ? source : UString("(?:)"), postfix));
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index f5db720b427056633217355b2c1ed183663b47f8..d3979bdd216ed7b8e70f8ab6fc675fc99d3cddb9 100644 (file)
@@ -27,7 +27,7 @@ namespace JSC {
 
     class RegExpPrototype : public JSObject {
     public:
 
     class RegExpPrototype : public JSObject {
     public:
-        RegExpPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+        RegExpPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
index 5c2edab68b683e44bdbd6d75dc309e93cb9140ae..981794bee91c7faa2e1dad1558834ea539edf717 100644 (file)
@@ -36,8 +36,8 @@ void ScopeChainNode::print() const
     ScopeChainIterator scopeEnd = end();
     for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
         JSObject* o = *scopeIter;
     ScopeChainIterator scopeEnd = end();
     for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
         JSObject* o = *scopeIter;
-        PropertyNameArray propertyNames(globalObject()->globalExec());
-        o->getPropertyNames(globalObject()->globalExec(), propertyNames);
+        PropertyNameArray propertyNames(globalObject->globalExec());
+        o->getPropertyNames(globalObject->globalExec(), propertyNames);
         PropertyNameArray::const_iterator propEnd = propertyNames.end();
 
         fprintf(stderr, "----- [scope %p] -----\n", o);
         PropertyNameArray::const_iterator propEnd = propertyNames.end();
 
         fprintf(stderr, "----- [scope %p] -----\n", o);
@@ -56,7 +56,7 @@ int ScopeChain::localDepth() const
     int scopeDepth = 0;
     ScopeChainIterator iter = this->begin();
     ScopeChainIterator end = this->end();
     int scopeDepth = 0;
     ScopeChainIterator iter = this->begin();
     ScopeChainIterator end = this->end();
-    while (!(*iter)->isObject(&JSActivation::info)) {
+    while (!(*iter)->inherits(&JSActivation::info)) {
         ++iter;
         if (iter == end)
             break;
         ++iter;
         if (iter == end)
             break;
index 17aff24ec102fa152e2e686fd9d3712fab9a4db6..0b15b67b39a0381b2f27a53422bd2fc75461bcfd 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -28,18 +28,21 @@ namespace JSC {
     class JSGlobalData;
     class JSGlobalObject;
     class JSObject;
     class JSGlobalData;
     class JSGlobalObject;
     class JSObject;
+    class MarkStack;
     class ScopeChainIterator;
     
     class ScopeChainNode : public FastAllocBase {
     public:
     class ScopeChainIterator;
     
     class ScopeChainNode : public FastAllocBase {
     public:
-        ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSObject* globalThis)
+        ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
             : next(next)
             , object(object)
             , globalData(globalData)
             : next(next)
             , object(object)
             , globalData(globalData)
+            , globalObject(globalObject)
             , globalThis(globalThis)
             , refCount(1)
         {
             ASSERT(globalData);
             , globalThis(globalThis)
             , refCount(1)
         {
             ASSERT(globalData);
+            ASSERT(globalObject);
         }
 #ifndef NDEBUG
         // Due to the number of subtle and timing dependent bugs that have occurred due
         }
 #ifndef NDEBUG
         // Due to the number of subtle and timing dependent bugs that have occurred due
@@ -50,6 +53,7 @@ namespace JSC {
             next = 0;
             object = 0;
             globalData = 0;
             next = 0;
             object = 0;
             globalData = 0;
+            globalObject = 0;
             globalThis = 0;
         }
 #endif
             globalThis = 0;
         }
 #endif
@@ -57,6 +61,7 @@ namespace JSC {
         ScopeChainNode* next;
         JSObject* object;
         JSGlobalData* globalData;
         ScopeChainNode* next;
         JSObject* object;
         JSGlobalData* globalData;
+        JSGlobalObject* globalObject;
         JSObject* globalThis;
         int refCount;
 
         JSObject* globalThis;
         int refCount;
 
@@ -81,9 +86,6 @@ namespace JSC {
         ScopeChainIterator begin() const;
         ScopeChainIterator end() const;
 
         ScopeChainIterator begin() const;
         ScopeChainIterator end() const;
 
-        JSGlobalObject* globalObject() const; // defined in JSGlobalObject.h
-        JSObject* globalThisObject() const { return globalThis; }
-
 #ifndef NDEBUG        
         void print() const;
 #endif
 #ifndef NDEBUG        
         void print() const;
 #endif
@@ -92,7 +94,7 @@ namespace JSC {
     inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
     {
         ASSERT(o);
     inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
     {
         ASSERT(o);
-        return new ScopeChainNode(this, o, globalData, globalThis);
+        return new ScopeChainNode(this, o, globalData, globalObject, globalThis);
     }
 
     inline ScopeChainNode* ScopeChainNode::pop()
     }
 
     inline ScopeChainNode* ScopeChainNode::pop()
@@ -162,8 +164,8 @@ namespace JSC {
         {
         }
 
         {
         }
 
-        ScopeChain(JSObject* o, JSGlobalData* globalData, JSObject* globalThis)
-            : m_node(new ScopeChainNode(0, o, globalData, globalThis))
+        ScopeChain(JSObject* o, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
+            : m_node(new ScopeChainNode(0, o, globalData, globalObject, globalThis))
         {
         }
 
         {
         }
 
@@ -202,9 +204,9 @@ namespace JSC {
         void pop() { m_node = m_node->pop(); }
         void clear() { m_node->deref(); m_node = 0; }
         
         void pop() { m_node = m_node->pop(); }
         void clear() { m_node->deref(); m_node = 0; }
         
-        JSGlobalObject* globalObject() const { return m_node->globalObject(); }
+        JSGlobalObject* globalObject() const { return m_node->globalObject; }
 
 
-        void mark() const;
+        void markAggregate(MarkStack&) const;
 
         // Caution: this should only be used if the codeblock this is being used
         // with needs a full scope chain, otherwise this returns the depth of
 
         // Caution: this should only be used if the codeblock this is being used
         // with needs a full scope chain, otherwise this returns the depth of
index b80b8ef9bf6e55f1c7af2c0a2edfa1ea2c906017..984d101368a9bc9ca078da27accb02f75a1deed6 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2006, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 
 namespace JSC {
 
 
 namespace JSC {
 
-    inline void ScopeChain::mark() const
+    inline void ScopeChain::markAggregate(MarkStack& markStack) const
     {
     {
-        for (ScopeChainNode* n = m_node; n; n = n->next) {
-            JSObject* o = n->object;
-            if (!o->marked())
-                o->mark();
-        }
+        for (ScopeChainNode* n = m_node; n; n = n->next)
+            markStack.append(n->object);
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index 87b49f05a5ce7eb1a85d90264ae732a485c4adca..78bd4e42c4f7b4290695a23dbe11bdd5285b674e 100644 (file)
 namespace JSC {
 static const unsigned numCharactersToStore = 0x100;
 
 namespace JSC {
 static const unsigned numCharactersToStore = 0x100;
 
-class SmallStringsStorage : Noncopyable {
+static inline bool isMarked(JSString* string)
+{
+    return string && Heap::isCellMarked(string);
+}
+
+class SmallStringsStorage : public Noncopyable {
 public:
     SmallStringsStorage();
 
     UString::Rep* rep(unsigned char character) { return &m_reps[character]; }
 
 private:
 public:
     SmallStringsStorage();
 
     UString::Rep* rep(unsigned char character) { return &m_reps[character]; }
 
 private:
-    UChar m_characters[numCharactersToStore];
-    UString::BaseString m_base;
     UString::Rep m_reps[numCharactersToStore];
 };
 
 SmallStringsStorage::SmallStringsStorage()
     UString::Rep m_reps[numCharactersToStore];
 };
 
 SmallStringsStorage::SmallStringsStorage()
-    : m_base(m_characters, numCharactersToStore)
 {
 {
-    m_base.rc = numCharactersToStore + 1;
-    // make sure UString doesn't try to reuse the buffer by pretending we have one more character in it
-    m_base.usedCapacity = numCharactersToStore + 1;
-    m_base.capacity = numCharactersToStore + 1;
-    m_base.checkConsistency();
-
-    for (unsigned i = 0; i < numCharactersToStore; ++i)
-        m_characters[i] = i;
-
-    memset(&m_reps, 0, sizeof(m_reps));
+    UChar* characterBuffer = 0;
+    RefPtr<UStringImpl> baseString = UStringImpl::createUninitialized(numCharactersToStore, characterBuffer);
     for (unsigned i = 0; i < numCharactersToStore; ++i) {
     for (unsigned i = 0; i < numCharactersToStore; ++i) {
-        m_reps[i].offset = i;
-        m_reps[i].len = 1;
-        m_reps[i].rc = 1;
-        m_reps[i].setBaseString(&m_base);
-        m_reps[i].checkConsistency();
+        characterBuffer[i] = i;
+        new (&m_reps[i]) UString::Rep(&characterBuffer[i], 1, PassRefPtr<UStringImpl>(baseString));
     }
 }
 
 SmallStrings::SmallStrings()
     }
 }
 
 SmallStrings::SmallStrings()
-    : m_emptyString(0)
-    , m_storage(0)
 {
     COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
 {
     COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
-
-    for (unsigned i = 0; i < numCharactersToStore; ++i)
-        m_singleCharacterStrings[i] = 0;
+    clear();
 }
 
 SmallStrings::~SmallStrings()
 {
 }
 
 }
 
 SmallStrings::~SmallStrings()
 {
 }
 
-void SmallStrings::mark()
+void SmallStrings::markChildren(MarkStack& markStack)
 {
 {
-    if (m_emptyString && !m_emptyString->marked())
-        m_emptyString->mark();
+    /*
+       Our hypothesis is that small strings are very common. So, we cache them
+       to avoid GC churn. However, in cases where this hypothesis turns out to
+       be false -- including the degenerate case where all JavaScript execution
+       has terminated -- we don't want to waste memory.
+
+       To test our hypothesis, we check if any small string has been marked. If
+       so, it's probably reasonable to mark the rest. If not, we clear the cache.
+     */
+
+    bool isAnyStringMarked = isMarked(m_emptyString);
+    for (unsigned i = 0; i < numCharactersToStore && !isAnyStringMarked; ++i)
+        isAnyStringMarked = isMarked(m_singleCharacterStrings[i]);
+    
+    if (!isAnyStringMarked) {
+        clear();
+        return;
+    }
+    
+    if (m_emptyString)
+        markStack.append(m_emptyString);
     for (unsigned i = 0; i < numCharactersToStore; ++i) {
     for (unsigned i = 0; i < numCharactersToStore; ++i) {
-        if (m_singleCharacterStrings[i] && !m_singleCharacterStrings[i]->marked())
-            m_singleCharacterStrings[i]->mark();
+        if (m_singleCharacterStrings[i])
+            markStack.append(m_singleCharacterStrings[i]);
     }
 }
 
     }
 }
 
+void SmallStrings::clear()
+{
+    m_emptyString = 0;
+    for (unsigned i = 0; i < numCharactersToStore; ++i)
+        m_singleCharacterStrings[i] = 0;
+}
+
 unsigned SmallStrings::count() const
 {
     unsigned count = 0;
 unsigned SmallStrings::count() const
 {
     unsigned count = 0;
index e7f11704ba67d9aaab1c833ae28274fc71780429..cc11d0ace5c1e56ccf885304d2ccdcd4843f8f97 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,10 +33,10 @@ namespace JSC {
 
     class JSGlobalData;
     class JSString;
 
     class JSGlobalData;
     class JSString;
-
+    class MarkStack;
     class SmallStringsStorage;
 
     class SmallStringsStorage;
 
-    class SmallStrings : Noncopyable {
+    class SmallStrings : public Noncopyable {
     public:
         SmallStrings();
         ~SmallStrings();
     public:
         SmallStrings();
         ~SmallStrings();
@@ -56,7 +56,8 @@ namespace JSC {
 
         UString::Rep* singleCharacterStringRep(unsigned char character);
 
 
         UString::Rep* singleCharacterStringRep(unsigned char character);
 
-        void mark();
+        void markChildren(MarkStack&);
+        void clear();
 
         unsigned count() const;
 
 
         unsigned count() const;
 
diff --git a/runtime/StringBuilder.h b/runtime/StringBuilder.h
new file mode 100644 (file)
index 0000000..8e18d37
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef StringBuilder_h
+#define StringBuilder_h
+
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class StringBuilder {
+public:
+    void append(const UChar u)
+    {
+        buffer.append(u);
+    }
+
+    void append(const char* str)
+    {
+        buffer.append(str, strlen(str));
+    }
+
+    void append(const char* str, size_t len)
+    {
+        buffer.reserveCapacity(buffer.size() + len);
+        for (size_t i = 0; i < len; i++)
+            buffer.append(static_cast<unsigned char>(str[i]));
+    }
+
+    void append(const UChar* str, size_t len)
+    {
+        buffer.append(str, len);
+    }
+
+    void append(const UString& str)
+    {
+        buffer.append(str.data(), str.size());
+    }
+
+    bool isEmpty() { return buffer.isEmpty(); }
+    void reserveCapacity(size_t newCapacity) { buffer.reserveCapacity(newCapacity); }
+    void resize(size_t size) { buffer.resize(size); }
+    size_t size() const { return buffer.size(); }
+
+    UChar operator[](size_t i) const { return buffer.at(i); }
+
+    UString release()
+    {
+        buffer.shrinkToFit();
+        return UString::adopt(buffer);
+    }
+
+private:
+    Vector<UChar, 64> buffer;
+};
+
+}
+
+#endif
index 638044587437a1d3c45873efa33cda09c41d8337..c7b62bfc81a05f77346a2211b1d9bef8bb989614 100644 (file)
@@ -30,12 +30,12 @@ namespace JSC {
 
 static NEVER_INLINE JSValue stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args)
 {
 
 static NEVER_INLINE JSValue stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args)
 {
-    UChar* buf = static_cast<UChar*>(fastMalloc(args.size() * sizeof(UChar)));
-    UChar* p = buf;
-    ArgList::const_iterator end = args.end();
-    for (ArgList::const_iterator it = args.begin(); it != end; ++it)
-        *p++ = static_cast<UChar>((*it).toUInt32(exec));
-    return jsString(exec, UString(buf, p - buf, false));
+    unsigned length = args.size();
+    UChar* buf;
+    PassRefPtr<UStringImpl> impl = UStringImpl::createUninitialized(length, buf);
+    for (unsigned i = 0; i < length; ++i)
+        buf[i] = static_cast<UChar>(args.at(i).toUInt32(exec));
+    return jsString(exec, impl);
 }
 
 static JSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec, JSObject*, JSValue, const ArgList& args)
 }
 
 static JSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec, JSObject*, JSValue, const ArgList& args)
@@ -47,7 +47,7 @@ static JSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec, JSObject*, JSVa
 
 ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
 
 
 ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
 
-StringConstructor::StringConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, StringPrototype* stringPrototype)
+StringConstructor::StringConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, StringPrototype* stringPrototype)
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, stringPrototype->classInfo()->className))
 {
     // ECMA 15.5.3.1 String.prototype
     : InternalFunction(&exec->globalData(), structure, Identifier(exec, stringPrototype->classInfo()->className))
 {
     // ECMA 15.5.3.1 String.prototype
index 7d52c69e18a257d8dc6a7ff8e6991ce5a546d48a..e511f7bf2ea0a76ff5082bd30b66b7a2c66e972c 100644 (file)
@@ -29,7 +29,7 @@ namespace JSC {
 
     class StringConstructor : public InternalFunction {
     public:
 
     class StringConstructor : public InternalFunction {
     public:
-        StringConstructor(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure, StringPrototype*);
+        StringConstructor(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, StringPrototype*);
 
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
 
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
index fb44498a57e1a7274358abcbe8f9eb4bd14dc6b9..f8e0e872b40c549006080e50f3228bedf98b91b3 100644 (file)
@@ -29,19 +29,19 @@ ASSERT_CLASS_FITS_IN_CELL(StringObject);
 
 const ClassInfo StringObject::info = { "String", 0, 0, 0 };
 
 
 const ClassInfo StringObject::info = { "String", 0, 0, 0 };
 
-StringObject::StringObject(ExecState* exec, PassRefPtr<Structure> structure)
+StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure)
     : JSWrapperObject(structure)
 {
     setInternalValue(jsEmptyString(exec));
 }
 
     : JSWrapperObject(structure)
 {
     setInternalValue(jsEmptyString(exec));
 }
 
-StringObject::StringObject(PassRefPtr<Structure> structure, JSString* string)
+StringObject::StringObject(NonNullPassRefPtr<Structure> structure, JSString* string)
     : JSWrapperObject(structure)
 {
     setInternalValue(string);
 }
 
     : JSWrapperObject(structure)
 {
     setInternalValue(string);
 }
 
-StringObject::StringObject(ExecState* exec, PassRefPtr<Structure> structure, const UString& string)
+StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string)
     : JSWrapperObject(structure)
 {
     setInternalValue(jsString(exec, string));
     : JSWrapperObject(structure)
 {
     setInternalValue(jsString(exec, string));
@@ -61,6 +61,13 @@ bool StringObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Pr
     return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
 }
 
     return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
 }
 
+bool StringObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    if (internalValue()->getStringPropertyDescriptor(exec, propertyName, descriptor))
+        return true;    
+    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
 void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     if (propertyName == exec->propertyNames().length)
 void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     if (propertyName == exec->propertyNames().length)
@@ -72,30 +79,21 @@ bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyNam
 {
     if (propertyName == exec->propertyNames().length)
         return false;
 {
     if (propertyName == exec->propertyNames().length)
         return false;
+    bool isStrictUInt32;
+    unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
+    if (isStrictUInt32 && internalValue()->canGetIndex(i))
+        return false;
     return JSObject::deleteProperty(exec, propertyName);
 }
 
     return JSObject::deleteProperty(exec, propertyName);
 }
 
-void StringObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void StringObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    int size = internalValue()->value().size();
+    int size = internalValue()->length();
     for (int i = 0; i < size; ++i)
         propertyNames.add(Identifier(exec, UString::from(i)));
     for (int i = 0; i < size; ++i)
         propertyNames.add(Identifier(exec, UString::from(i)));
-    return JSObject::getPropertyNames(exec, propertyNames);
-}
-
-UString StringObject::toString(ExecState*) const
-{
-    return internalValue()->value();
-}
-
-UString StringObject::toThisString(ExecState*) const
-{
-    return internalValue()->value();
-}
-
-JSString* StringObject::toThisJSString(ExecState*)
-{
-    return internalValue();
+    if (mode == IncludeDontEnumProperties)
+        propertyNames.add(exec->propertyNames().length);
+    return JSObject::getOwnPropertyNames(exec, propertyNames, mode);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index ea3a0454664a771a580c7a9a34252e8ed7dc4b52..e3add77b92bbff5843186b46dec4ed5cedc07738 100644 (file)
@@ -28,17 +28,18 @@ namespace JSC {
 
     class StringObject : public JSWrapperObject {
     public:
 
     class StringObject : public JSWrapperObject {
     public:
-        StringObject(ExecState*, PassRefPtr<Structure>);
-        StringObject(ExecState*, PassRefPtr<Structure>, const UString&);
+        StringObject(ExecState*, NonNullPassRefPtr<Structure>);
+        StringObject(ExecState*, NonNullPassRefPtr<Structure>, const UString&);
 
         static StringObject* create(ExecState*, JSString*);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
 
         static StringObject* create(ExecState*, JSString*);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         virtual void put(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
 
         virtual void put(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
-        virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const JS_EXPORTDATA ClassInfo info;
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const JS_EXPORTDATA ClassInfo info;
@@ -47,16 +48,12 @@ namespace JSC {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
 
         static PassRefPtr<Structure> createStructure(JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType));
+            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
         }
 
     protected:
         }
 
     protected:
-        StringObject(PassRefPtr<Structure>, JSString*);
-
-    private:
-        virtual UString toString(ExecState*) const;
-        virtual UString toThisString(ExecState*) const;
-        virtual JSString* toThisJSString(ExecState*);
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSWrapperObject::StructureFlags;
+        StringObject(NonNullPassRefPtr<Structure>, JSString*);
   };
 
     StringObject* asStringObject(JSValue);
   };
 
     StringObject* asStringObject(JSValue);
index bc5c0a5b22eb9f6fa88578215ce806ae185a2aa4..43c3e3839a41f09bc01cc40d1e36ecc2566d6bc3 100644 (file)
@@ -37,16 +37,18 @@ namespace JSC {
         }
 
     private:
         }
 
     private:
-        StringObjectThatMasqueradesAsUndefined(ExecState* exec, PassRefPtr<Structure> structure, const UString& string)
+        StringObjectThatMasqueradesAsUndefined(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string)
             : StringObject(exec, structure, string)
         {
         }
 
         static PassRefPtr<Structure> createStructure(JSValue proto) 
         { 
             : StringObject(exec, structure, string)
         {
         }
 
         static PassRefPtr<Structure> createStructure(JSValue proto) 
         { 
-            return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined)); 
+            return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
         }
 
         }
 
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | MasqueradesAsUndefined | OverridesGetPropertyNames | StringObject::StructureFlags;
+
         virtual bool toBoolean(ExecState*) const { return false; }
     };
  
         virtual bool toBoolean(ExecState*) const { return false; }
     };
  
index 531a302d5ea40fdd8f12facf53d85af7f290da5d..d002e071a331f55f7b69abad26ee5697dedc73de 100644 (file)
 #include "StringPrototype.h"
 
 #include "CachedCall.h"
 #include "StringPrototype.h"
 
 #include "CachedCall.h"
+#include "Error.h"
+#include "Executable.h"
+#include "JSGlobalObjectFunctions.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "ObjectPrototype.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "ObjectPrototype.h"
+#include "Operations.h"
 #include "PropertyNameArray.h"
 #include "RegExpConstructor.h"
 #include "RegExpObject.h"
 #include "PropertyNameArray.h"
 #include "RegExpConstructor.h"
 #include "RegExpObject.h"
@@ -70,6 +74,10 @@ static JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState*, JSObject*, JSVa
 static JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState*, JSObject*, JSValue, const ArgList&);
 static JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState*, JSObject*, JSValue, const ArgList&);
 
 static JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState*, JSObject*, JSValue, const ArgList&);
 static JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState*, JSObject*, JSValue, const ArgList&);
 
+static JSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*, JSObject*, JSValue, const ArgList&);
+
 }
 
 #include "StringPrototype.lut.h"
 }
 
 #include "StringPrototype.lut.h"
@@ -115,11 +123,14 @@ const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, Exec
     fontsize              stringProtoFuncFontsize          DontEnum|Function       1
     anchor                stringProtoFuncAnchor            DontEnum|Function       1
     link                  stringProtoFuncLink              DontEnum|Function       1
     fontsize              stringProtoFuncFontsize          DontEnum|Function       1
     anchor                stringProtoFuncAnchor            DontEnum|Function       1
     link                  stringProtoFuncLink              DontEnum|Function       1
+    trim                  stringProtoFuncTrim              DontEnum|Function       0
+    trimLeft              stringProtoFuncTrimLeft          DontEnum|Function       0
+    trimRight             stringProtoFuncTrimRight         DontEnum|Function       0
 @end
 */
 
 // ECMA 15.5.4
 @end
 */
 
 // ECMA 15.5.4
-StringPrototype::StringPrototype(ExecState* exec, PassRefPtr<Structure> structure)
+StringPrototype::StringPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
     : StringObject(exec, structure)
 {
     // The constructor will be added later, after StringConstructor has been built
     : StringObject(exec, structure)
 {
     // The constructor will be added later, after StringConstructor has been built
@@ -131,14 +142,18 @@ bool StringPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& prop
     return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, slot);
 }
 
     return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, slot);
 }
 
+bool StringPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, descriptor);
+}
+
 // ------------------------------ Functions --------------------------
 
 // ------------------------------ Functions --------------------------
 
-static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg)
+static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacement, const UString& source, const int* ovector, RegExp* reg, int i)
 {
 {
-    UString substitutedReplacement;
+    Vector<UChar> substitutedReplacement;
     int offset = 0;
     int offset = 0;
-    int i = -1;
-    while ((i = replacement.find('$', i + 1)) != -1) {
+    do {
         if (i + 1 == replacement.size())
             break;
 
         if (i + 1 == replacement.size())
             break;
 
@@ -190,15 +205,21 @@ static inline UString substituteBackreferences(const UString& replacement, const
         i += 1 + advance;
         offset = i + 1;
         substitutedReplacement.append(source.data() + backrefStart, backrefLength);
         i += 1 + advance;
         offset = i + 1;
         substitutedReplacement.append(source.data() + backrefStart, backrefLength);
-    }
-
-    if (!offset)
-        return replacement;
+    } while ((i = replacement.find('$', i + 1)) != -1);
 
     if (replacement.size() - offset)
         substitutedReplacement.append(replacement.data() + offset, replacement.size() - offset);
 
 
     if (replacement.size() - offset)
         substitutedReplacement.append(replacement.data() + offset, replacement.size() - offset);
 
-    return substitutedReplacement;
+    substitutedReplacement.shrinkToFit();
+    return UString::adopt(substitutedReplacement);
+}
+
+static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg)
+{
+    int i = replacement.find('$', 0);
+    if (UNLIKELY(i != -1))
+        return substituteBackreferencesSlow(replacement, source, ovector, reg, i);
+    return replacement;
 }
 
 static inline int localeCompare(const UString& a, const UString& b)
 }
 
 static inline int localeCompare(const UString& a, const UString& b)
@@ -209,7 +230,7 @@ static inline int localeCompare(const UString& a, const UString& b)
 JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
     JSString* sourceVal = thisValue.toThisJSString(exec);
 JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
     JSString* sourceVal = thisValue.toThisJSString(exec);
-    const UString& source = sourceVal->value();
+    const UString& source = sourceVal->value(exec);
 
     JSValue pattern = args.at(0);
 
 
     JSValue pattern = args.at(0);
 
@@ -220,7 +241,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
     if (callType == CallTypeNone)
         replacementString = replacement.toString(exec);
 
     if (callType == CallTypeNone)
         replacementString = replacement.toString(exec);
 
-    if (pattern.isObject(&RegExpObject::info)) {
+    if (pattern.inherits(&RegExpObject::info)) {
         RegExp* reg = asRegExpObject(pattern)->regExp();
         bool global = reg->global();
 
         RegExp* reg = asRegExpObject(pattern)->regExp();
         bool global = reg->global();
 
@@ -242,7 +263,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
                 return jsNull();
             while (true) {
                 int matchIndex;
                 return jsNull();
             while (true) {
                 int matchIndex;
-                int matchLen;
+                int matchLen = 0;
                 int* ovector;
                 regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
                 if (matchIndex < 0)
                 int* ovector;
                 regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
                 if (matchIndex < 0)
@@ -266,7 +287,8 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
                 cachedCall.setArgument(i++, sourceVal);
                 
                 cachedCall.setThis(exec->globalThisValue());
                 cachedCall.setArgument(i++, sourceVal);
                 
                 cachedCall.setThis(exec->globalThisValue());
-                replacements.append(cachedCall.call().toString(cachedCall.newCallFrame()));
+                JSValue result = cachedCall.call();
+                replacements.append(result.toString(cachedCall.newCallFrame(exec)));
                 if (exec->hadException())
                     break;
 
                 if (exec->hadException())
                     break;
 
@@ -283,7 +305,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
         } else {
             do {
                 int matchIndex;
         } else {
             do {
                 int matchIndex;
-                int matchLen;
+                int matchLen = 0;
                 int* ovector;
                 regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
                 if (matchIndex < 0)
                 int* ovector;
                 regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
                 if (matchIndex < 0)
@@ -365,7 +387,7 @@ JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec, JSObject*, JSValu
     if (thisValue.isString())
         return thisValue;
 
     if (thisValue.isString())
         return thisValue;
 
-    if (thisValue.isObject(&StringObject::info))
+    if (thisValue.inherits(&StringObject::info))
         return asStringObject(thisValue)->internalValue();
 
     return throwError(exec, TypeError);
         return asStringObject(thisValue)->internalValue();
 
     return throwError(exec, TypeError);
@@ -407,12 +429,14 @@ JSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSVa
 
 JSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
 
 JSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isString() && (args.size() == 1)) {
+        JSValue v = args.at(0);
+        return v.isString()
+            ? jsString(exec, asString(thisValue), asString(v))
+            : jsString(exec, asString(thisValue), v.toString(exec));
+    }
 
 
-    ArgList::const_iterator end = args.end();
-    for (ArgList::const_iterator it = args.begin(); it != end; ++it)
-        s += (*it).toString(exec);
-    return jsString(exec, s);
+    return jsString(exec, thisValue, args);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
@@ -454,6 +478,11 @@ JSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSV
         dpos = 0;
     else if (!(dpos <= len)) // true for NaN
         dpos = len;
         dpos = 0;
     else if (!(dpos <= len)) // true for NaN
         dpos = len;
+#if OS(SYMBIAN)
+    // Work around for broken NaN compare operator
+    else if (isnan(dpos))
+        dpos = len;
+#endif
     return jsNumber(exec, s.rfind(u2, static_cast<int>(dpos)));
 }
 
     return jsNumber(exec, s.rfind(u2, static_cast<int>(dpos)));
 }
 
@@ -466,7 +495,7 @@ JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue t
     UString u = s;
     RefPtr<RegExp> reg;
     RegExpObject* imp = 0;
     UString u = s;
     RefPtr<RegExp> reg;
     RegExpObject* imp = 0;
-    if (a0.isObject(&RegExpObject::info))
+    if (a0.inherits(&RegExpObject::info))
         reg = asRegExpObject(a0)->regExp();
     else {
         /*
         reg = asRegExpObject(a0)->regExp();
     else {
         /*
@@ -478,7 +507,7 @@ JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue t
     }
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
     int pos;
     }
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
     int pos;
-    int matchLength;
+    int matchLength = 0;
     regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
     if (!(reg->global())) {
         // case without 'g' flag is handled like RegExp.prototype.exec
     regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
     if (!(reg->global())) {
         // case without 'g' flag is handled like RegExp.prototype.exec
@@ -516,7 +545,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue
 
     UString u = s;
     RefPtr<RegExp> reg;
 
     UString u = s;
     RefPtr<RegExp> reg;
-    if (a0.isObject(&RegExpObject::info))
+    if (a0.inherits(&RegExpObject::info))
         reg = asRegExpObject(a0)->regExp();
     else { 
         /*
         reg = asRegExpObject(a0)->regExp();
     else { 
         /*
@@ -528,7 +557,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue
     }
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
     int pos;
     }
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
     int pos;
-    int matchLength;
+    int matchLength = 0;
     regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
     return jsNumber(exec, pos);
 }
     regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
     return jsNumber(exec, pos);
 }
@@ -568,7 +597,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue t
     unsigned i = 0;
     int p0 = 0;
     unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec);
     unsigned i = 0;
     int p0 = 0;
     unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec);
-    if (a0.isObject(&RegExpObject::info)) {
+    if (a0.inherits(&RegExpObject::info)) {
         RegExp* reg = asRegExpObject(a0)->regExp();
         if (s.isEmpty() && reg->match(s, 0) >= 0) {
             // empty string matched by regexp -> empty array
         RegExp* reg = asRegExpObject(a0)->regExp();
         if (s.isEmpty() && reg->match(s, 0) >= 0) {
             // empty string matched by regexp -> empty array
@@ -676,7 +705,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec, JSObject*, JSVal
 JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     JSString* sVal = thisValue.toThisJSString(exec);
 JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     JSString* sVal = thisValue.toThisJSString(exec);
-    const UString& s = sVal->value();
+    const UString& s = sVal->value(exec);
 
     int sSize = s.size();
     if (!sSize)
 
     int sSize = s.size();
     if (!sSize)
@@ -692,7 +721,7 @@ JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSV
         buffer[i] = toASCIILower(c);
     }
     if (!(ored & ~0x7f))
         buffer[i] = toASCIILower(c);
     }
     if (!(ored & ~0x7f))
-        return jsString(exec, UString(buffer.releaseBuffer(), sSize, false));
+        return jsString(exec, UString::adopt(buffer));
 
     bool error;
     int length = Unicode::toLower(buffer.data(), sSize, sData, sSize, &error);
 
     bool error;
     int length = Unicode::toLower(buffer.data(), sSize, sData, sSize, &error);
@@ -702,15 +731,18 @@ JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSV
         if (error)
             return sVal;
     }
         if (error)
             return sVal;
     }
-    if (length == sSize && memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
-        return sVal;
-    return jsString(exec, UString(buffer.releaseBuffer(), length, false));
+    if (length == sSize) {
+        if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
+            return sVal;
+    } else
+        buffer.resize(length);
+    return jsString(exec, UString::adopt(buffer));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     JSString* sVal = thisValue.toThisJSString(exec);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     JSString* sVal = thisValue.toThisJSString(exec);
-    const UString& s = sVal->value();
+    const UString& s = sVal->value(exec);
 
     int sSize = s.size();
     if (!sSize)
 
     int sSize = s.size();
     if (!sSize)
@@ -726,7 +758,7 @@ JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSV
         buffer[i] = toASCIIUpper(c);
     }
     if (!(ored & ~0x7f))
         buffer[i] = toASCIIUpper(c);
     }
     if (!(ored & ~0x7f))
-        return jsString(exec, UString(buffer.releaseBuffer(), sSize, false));
+        return jsString(exec, UString::adopt(buffer));
 
     bool error;
     int length = Unicode::toUpper(buffer.data(), sSize, sData, sSize, &error);
 
     bool error;
     int length = Unicode::toUpper(buffer.data(), sSize, sData, sSize, &error);
@@ -736,9 +768,12 @@ JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSV
         if (error)
             return sVal;
     }
         if (error)
             return sVal;
     }
-    if (length == sSize && memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
-        return sVal;
-    return jsString(exec, UString(buffer.releaseBuffer(), length, false));
+    if (length == sSize) {
+        if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
+            return sVal;
+    } else
+        buffer.resize(length);
+    return jsString(exec, UString::adopt(buffer));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
@@ -754,62 +789,62 @@ JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, J
 JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
 JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsNontrivialString(exec, "<big>" + s + "</big>");
+    return jsNontrivialString(exec, makeString("<big>", s, "</big>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsNontrivialString(exec, "<small>" + s + "</small>");
+    return jsNontrivialString(exec, makeString("<small>", s, "</small>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsNontrivialString(exec, "<blink>" + s + "</blink>");
+    return jsNontrivialString(exec, makeString("<blink>", s, "</blink>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsNontrivialString(exec, "<b>" + s + "</b>");
+    return jsNontrivialString(exec, makeString("<b>", s, "</b>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsString(exec, "<tt>" + s + "</tt>");
+    return jsString(exec, makeString("<tt>", s, "</tt>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsNontrivialString(exec, "<i>" + s + "</i>");
+    return jsNontrivialString(exec, makeString("<i>", s, "</i>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsNontrivialString(exec, "<strike>" + s + "</strike>");
+    return jsNontrivialString(exec, makeString("<strike>", s, "</strike>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsNontrivialString(exec, "<sub>" + s + "</sub>");
+    return jsNontrivialString(exec, makeString("<sub>", s, "</sub>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsNontrivialString(exec, "<sup>" + s + "</sup>");
+    return jsNontrivialString(exec, makeString("<sup>", s, "</sup>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
     UString s = thisValue.toThisString(exec);
     JSValue a0 = args.at(0);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
     UString s = thisValue.toThisString(exec);
     JSValue a0 = args.at(0);
-    return jsNontrivialString(exec, "<font color=\"" + a0.toString(exec) + "\">" + s + "</font>");
+    return jsNontrivialString(exec, makeString("<font color=\"", a0.toString(exec), "\">", s, "</font>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
@@ -821,8 +856,9 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu
     if (a0.getUInt32(smallInteger) && smallInteger <= 9) {
         unsigned stringSize = s.size();
         unsigned bufferSize = 22 + stringSize;
     if (a0.getUInt32(smallInteger) && smallInteger <= 9) {
         unsigned stringSize = s.size();
         unsigned bufferSize = 22 + stringSize;
-        UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar)));
-        if (!buffer)
+        UChar* buffer;
+        PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(bufferSize, buffer);
+        if (!impl)
             return jsUndefined();
         buffer[0] = '<';
         buffer[1] = 'f';
             return jsUndefined();
         buffer[0] = '<';
         buffer[1] = 'f';
@@ -847,17 +883,17 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu
         buffer[19 + stringSize] = 'n';
         buffer[20 + stringSize] = 't';
         buffer[21 + stringSize] = '>';
         buffer[19 + stringSize] = 'n';
         buffer[20 + stringSize] = 't';
         buffer[21 + stringSize] = '>';
-        return jsNontrivialString(exec, UString(buffer, bufferSize, false));
+        return jsNontrivialString(exec, impl);
     }
 
     }
 
-    return jsNontrivialString(exec, "<font size=\"" + a0.toString(exec) + "\">" + s + "</font>");
+    return jsNontrivialString(exec, makeString("<font size=\"", a0.toString(exec), "\">", s, "</font>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
     UString s = thisValue.toThisString(exec);
     JSValue a0 = args.at(0);
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 {
     UString s = thisValue.toThisString(exec);
     JSValue a0 = args.at(0);
-    return jsNontrivialString(exec, "<a name=\"" + a0.toString(exec) + "\">" + s + "</a>");
+    return jsNontrivialString(exec, makeString("<a name=\"", a0.toString(exec), "\">", s, "</a>"));
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
 }
 
 JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
@@ -869,8 +905,9 @@ JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue th
     unsigned linkTextSize = linkText.size();
     unsigned stringSize = s.size();
     unsigned bufferSize = 15 + linkTextSize + stringSize;
     unsigned linkTextSize = linkText.size();
     unsigned stringSize = s.size();
     unsigned bufferSize = 15 + linkTextSize + stringSize;
-    UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar)));
-    if (!buffer)
+    UChar* buffer;
+    PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(bufferSize, buffer);
+    if (!impl)
         return jsUndefined();
     buffer[0] = '<';
     buffer[1] = 'a';
         return jsUndefined();
     buffer[0] = '<';
     buffer[1] = 'a';
@@ -889,7 +926,54 @@ JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue th
     buffer[12 + linkTextSize + stringSize] = '/';
     buffer[13 + linkTextSize + stringSize] = 'a';
     buffer[14 + linkTextSize + stringSize] = '>';
     buffer[12 + linkTextSize + stringSize] = '/';
     buffer[13 + linkTextSize + stringSize] = 'a';
     buffer[14 + linkTextSize + stringSize] = '>';
-    return jsNontrivialString(exec, UString(buffer, bufferSize, false));
+    return jsNontrivialString(exec, impl);
 }
 
 }
 
+enum {
+    TrimLeft = 1,
+    TrimRight = 2
+};
+
+static inline bool isTrimWhitespace(UChar c)
+{
+    return isStrWhiteSpace(c) || c == 0x200b;
+}
+
+static inline JSValue trimString(ExecState* exec, JSValue thisValue, int trimKind)
+{
+    UString str = thisValue.toThisString(exec);
+    int left = 0;
+    if (trimKind & TrimLeft) {
+        while (left < str.size() && isTrimWhitespace(str[left]))
+            left++;
+    }
+    int right = str.size();
+    if (trimKind & TrimRight) {
+        while (right > left && isTrimWhitespace(str[right - 1]))
+            right--;
+    }
+
+    // Don't gc allocate a new string if we don't have to.
+    if (left == 0 && right == str.size() && thisValue.isString())
+        return thisValue;
+
+    return jsString(exec, str.substr(left, right - left));
+}
+
+JSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+{
+    return trimString(exec, thisValue, TrimLeft | TrimRight);
+}
+
+JSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+{
+    return trimString(exec, thisValue, TrimLeft);
+}
+
+JSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+{
+    return trimString(exec, thisValue, TrimRight);
+}
+    
+    
 } // namespace JSC
 } // namespace JSC
index 6f5344e0aea41ab6ba27156e856340e9145a4a0f..3a6a2a39076b9fc24d094a5b8ce3dd0aca230a56 100644 (file)
@@ -29,9 +29,10 @@ namespace JSC {
 
     class StringPrototype : public StringObject {
     public:
 
     class StringPrototype : public StringObject {
     public:
-        StringPrototype(ExecState*, PassRefPtr<Structure>);
+        StringPrototype(ExecState*, NonNullPassRefPtr<Structure>);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
 
         virtual const ClassInfo* classInfo() const { return &info; }
         static const ClassInfo info;
index 3b078365ecaef0078e5536d16d08f8818e736bf6..546e2bf6e8cfc35d43b7d3072f3a413cc224fc8f 100644 (file)
 
 #include "Identifier.h"
 #include "JSObject.h"
 
 #include "Identifier.h"
 #include "JSObject.h"
+#include "JSPropertyNameIterator.h"
+#include "Lookup.h"
 #include "PropertyNameArray.h"
 #include "StructureChain.h"
 #include "PropertyNameArray.h"
 #include "StructureChain.h"
-#include "Lookup.h"
 #include <wtf/RefCountedLeakCounter.h>
 #include <wtf/RefPtr.h>
 
 #include <wtf/RefCountedLeakCounter.h>
 #include <wtf/RefPtr.h>
 
@@ -122,7 +123,7 @@ void Structure::dumpStatistics()
 #endif
 }
 
 #endif
 }
 
-Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
+Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
     : m_typeInfo(typeInfo)
     , m_prototype(prototype)
     , m_specificValueInPrevious(0)
     : m_typeInfo(typeInfo)
     , m_prototype(prototype)
     , m_specificValueInPrevious(0)
@@ -132,14 +133,13 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
     , m_dictionaryKind(NoneDictionaryKind)
     , m_isPinnedPropertyTable(false)
     , m_hasGetterSetterProperties(false)
     , m_dictionaryKind(NoneDictionaryKind)
     , m_isPinnedPropertyTable(false)
     , m_hasGetterSetterProperties(false)
-    , m_usingSingleTransitionSlot(true)
     , m_attributesInPrevious(0)
     , m_attributesInPrevious(0)
+    , m_specificFunctionThrashCount(0)
+    , m_anonymousSlotCount(anonymousSlotCount)
 {
     ASSERT(m_prototype);
     ASSERT(m_prototype.isObject() || m_prototype.isNull());
 
 {
     ASSERT(m_prototype);
     ASSERT(m_prototype.isObject() || m_prototype.isNull());
 
-    m_transitions.singleTransition = 0;
-
 #ifndef NDEBUG
 #if ENABLE(JSC_MULTIPLE_THREADS)
     MutexLocker protect(ignoreSetMutex);
 #ifndef NDEBUG
 #if ENABLE(JSC_MULTIPLE_THREADS)
     MutexLocker protect(ignoreSetMutex);
@@ -158,19 +158,13 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
 Structure::~Structure()
 {
     if (m_previous) {
 Structure::~Structure()
 {
     if (m_previous) {
-        if (m_previous->m_usingSingleTransitionSlot) {
-            m_previous->m_transitions.singleTransition = 0;
-        } else {
-            ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious));
-            m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious);
-        }
-    }
+        ASSERT(m_nameInPrevious);
+        m_previous->table.remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious);
 
 
-    if (m_cachedPropertyNameArrayData)
-        m_cachedPropertyNameArrayData->setCachedStructure(0);
-
-    if (!m_usingSingleTransitionSlot)
-        delete m_transitions.table;
+    }
+    
+    if (m_enumerationCache)
+        m_enumerationCache->setCachedStructure(0);
 
     if (m_propertyTable) {
         unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
 
     if (m_propertyTable) {
         unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
@@ -282,48 +276,11 @@ void Structure::materializePropertyMap()
     for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) {
         structure = structures[i];
         structure->m_nameInPrevious->ref();
     for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) {
         structure = structures[i];
         structure->m_nameInPrevious->ref();
-        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);
+        PropertyMapEntry entry(structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);
         insertIntoPropertyMapHashTable(entry);
     }
 }
 
         insertIntoPropertyMapHashTable(entry);
     }
 }
 
-void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
-{
-    bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary());
-
-    if (shouldCache && m_cachedPropertyNameArrayData) {
-        if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) {
-            propertyNames.setData(m_cachedPropertyNameArrayData);
-            return;
-        }
-        clearEnumerationCache();
-    }
-
-    getEnumerableNamesFromPropertyTable(propertyNames);
-    getEnumerableNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames);
-
-    if (m_prototype.isObject()) {
-        propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly.
-        asObject(m_prototype)->getPropertyNames(exec, propertyNames);
-    }
-
-    if (shouldCache) {
-        StructureChain* protoChain = prototypeChain(exec);
-        m_cachedPropertyNameArrayData = propertyNames.data();
-        if (!protoChain->isCacheable())
-            return;
-        m_cachedPropertyNameArrayData->setCachedPrototypeChain(protoChain);
-        m_cachedPropertyNameArrayData->setCachedStructure(this);
-    }
-}
-
-void Structure::clearEnumerationCache()
-{
-    if (m_cachedPropertyNameArrayData)
-        m_cachedPropertyNameArrayData->setCachedStructure(0);
-    m_cachedPropertyNameArrayData.clear();
-}
-
 void Structure::growPropertyStorageCapacity()
 {
     if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
 void Structure::growPropertyStorageCapacity()
 {
     if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
@@ -341,7 +298,7 @@ void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
     ASSERT(isDictionary());
     ASSERT(m_propertyTable);
 
     ASSERT(isDictionary());
     ASSERT(m_propertyTable);
 
-    unsigned i = rep->computedHash();
+    unsigned i = rep->existingHash();
 
 #if DUMP_PROPERTYMAP_STATS
     ++numProbes;
 
 #if DUMP_PROPERTYMAP_STATS
     ++numProbes;
@@ -359,7 +316,7 @@ void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
     ++numCollisions;
 #endif
 
     ++numCollisions;
 #endif
 
-    unsigned k = 1 | doubleHash(rep->computedHash());
+    unsigned k = 1 | doubleHash(rep->existingHash());
 
     while (1) {
         i += k;
 
     while (1) {
         i += k;
@@ -383,22 +340,12 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct
     ASSERT(!structure->isDictionary());
     ASSERT(structure->typeInfo().type() == ObjectType);
 
     ASSERT(!structure->isDictionary());
     ASSERT(structure->typeInfo().type() == ObjectType);
 
-    if (structure->m_usingSingleTransitionSlot) {
-        Structure* existingTransition = structure->m_transitions.singleTransition;
-        if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep()
-            && existingTransition->m_attributesInPrevious == attributes
-            && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0)) {
-
-            ASSERT(structure->m_transitions.singleTransition->m_offset != noOffset);
-            offset = structure->m_transitions.singleTransition->m_offset;
-            return existingTransition;
-        }
-    } else {
-        if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
-            ASSERT(existingTransition->m_offset != noOffset);
-            offset = existingTransition->m_offset;
-            return existingTransition;
-        }
+    if (Structure* existingTransition = structure->table.get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
+        ASSERT(existingTransition->m_offset != noOffset);
+        offset = existingTransition->m_offset + existingTransition->m_anonymousSlotCount;
+        ASSERT(offset >= structure->m_anonymousSlotCount);
+        ASSERT(structure->m_anonymousSlotCount == existingTransition->m_anonymousSlotCount);
+        return existingTransition;
     }
 
     return 0;
     }
 
     return 0;
@@ -409,17 +356,22 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
     ASSERT(!structure->isDictionary());
     ASSERT(structure->typeInfo().type() == ObjectType);
     ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
     ASSERT(!structure->isDictionary());
     ASSERT(structure->typeInfo().type() == ObjectType);
     ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
+    
+    if (structure->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
+        specificValue = 0;
 
     if (structure->transitionCount() > s_maxTransitionLength) {
         RefPtr<Structure> transition = toCacheableDictionaryTransition(structure);
         ASSERT(structure != transition);
         offset = transition->put(propertyName, attributes, specificValue);
 
     if (structure->transitionCount() > s_maxTransitionLength) {
         RefPtr<Structure> transition = toCacheableDictionaryTransition(structure);
         ASSERT(structure != transition);
         offset = transition->put(propertyName, attributes, specificValue);
+        ASSERT(offset >= structure->m_anonymousSlotCount);
+        ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
         if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
             transition->growPropertyStorageCapacity();
         return transition.release();
     }
 
         if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
             transition->growPropertyStorageCapacity();
         return transition.release();
     }
 
-    RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
+    RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo(), structure->anonymousSlotCount());
 
     transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
     transition->m_previous = structure;
 
     transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
     transition->m_previous = structure;
@@ -428,6 +380,8 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
     transition->m_specificValueInPrevious = specificValue;
     transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
     transition->m_specificValueInPrevious = specificValue;
     transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
+    transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
 
     if (structure->m_propertyTable) {
         if (structure->m_isPinnedPropertyTable)
 
     if (structure->m_propertyTable) {
         if (structure->m_isPinnedPropertyTable)
@@ -444,24 +398,14 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
     }
 
     offset = transition->put(propertyName, attributes, specificValue);
     }
 
     offset = transition->put(propertyName, attributes, specificValue);
+    ASSERT(offset >= structure->m_anonymousSlotCount);
+    ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
     if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
         transition->growPropertyStorageCapacity();
 
     if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
         transition->growPropertyStorageCapacity();
 
-    transition->m_offset = offset;
-
-    if (structure->m_usingSingleTransitionSlot) {
-        if (!structure->m_transitions.singleTransition) {
-            structure->m_transitions.singleTransition = transition.get();
-            return transition.release();
-        }
-
-        Structure* existingTransition = structure->m_transitions.singleTransition;
-        structure->m_usingSingleTransitionSlot = false;
-        StructureTransitionTable* transitionTable = new StructureTransitionTable;
-        structure->m_transitions.table = transitionTable;
-        transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious);
-    }
-    structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
+    transition->m_offset = offset - structure->m_anonymousSlotCount;
+    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
+    structure->table.add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
     return transition.release();
 }
 
     return transition.release();
 }
 
@@ -472,32 +416,40 @@ PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure,
     RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure);
 
     offset = transition->remove(propertyName);
     RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure);
 
     offset = transition->remove(propertyName);
+    ASSERT(offset >= structure->m_anonymousSlotCount);
+    ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
 
     return transition.release();
 }
 
 PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype)
 {
 
     return transition.release();
 }
 
 PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype)
 {
-    RefPtr<Structure> transition = create(prototype, structure->typeInfo());
+    RefPtr<Structure> transition = create(prototype, structure->typeInfo(), structure->anonymousSlotCount());
 
     transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
 
     transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
+    transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
 
     // Don't set m_offset, as one can not transition to this.
 
     structure->materializePropertyMapIfNecessary();
     transition->m_propertyTable = structure->copyPropertyTable();
     transition->m_isPinnedPropertyTable = true;
 
     // Don't set m_offset, as one can not transition to this.
 
     structure->materializePropertyMapIfNecessary();
     transition->m_propertyTable = structure->copyPropertyTable();
     transition->m_isPinnedPropertyTable = true;
-
+    
+    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
     return transition.release();
 }
 
 PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction)
 {
     return transition.release();
 }
 
 PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction)
 {
-    RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
+    ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount);
+    RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
 
     transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
 
     transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
+    transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount + 1;
 
     // Don't set m_offset, as one can not transition to this.
 
 
     // Don't set m_offset, as one can not transition to this.
 
@@ -505,24 +457,32 @@ PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structur
     transition->m_propertyTable = structure->copyPropertyTable();
     transition->m_isPinnedPropertyTable = true;
 
     transition->m_propertyTable = structure->copyPropertyTable();
     transition->m_isPinnedPropertyTable = true;
 
-    bool removed = transition->despecifyFunction(replaceFunction);
-    ASSERT_UNUSED(removed, removed);
-
+    if (transition->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
+        transition->despecifyAllFunctions();
+    else {
+        bool removed = transition->despecifyFunction(replaceFunction);
+        ASSERT_UNUSED(removed, removed);
+    }
+    
+    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
     return transition.release();
 }
 
 PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
 {
     return transition.release();
 }
 
 PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
 {
-    RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
+    RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
     transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;
     transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;
+    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
+    transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
 
     // Don't set m_offset, as one can not transition to this.
 
     structure->materializePropertyMapIfNecessary();
     transition->m_propertyTable = structure->copyPropertyTable();
     transition->m_isPinnedPropertyTable = true;
 
     // Don't set m_offset, as one can not transition to this.
 
     structure->materializePropertyMapIfNecessary();
     transition->m_propertyTable = structure->copyPropertyTable();
     transition->m_isPinnedPropertyTable = true;
-
+    
+    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
     return transition.release();
 }
 
     return transition.release();
 }
 
@@ -530,15 +490,18 @@ PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, Di
 {
     ASSERT(!structure->isUncacheableDictionary());
     
 {
     ASSERT(!structure->isUncacheableDictionary());
     
-    RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
+    RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo(), structure->anonymousSlotCount());
     transition->m_dictionaryKind = kind;
     transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
     transition->m_dictionaryKind = kind;
     transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
     transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
+    transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
     
     structure->materializePropertyMapIfNecessary();
     transition->m_propertyTable = structure->copyPropertyTable();
     transition->m_isPinnedPropertyTable = true;
     
     
     structure->materializePropertyMapIfNecessary();
     transition->m_propertyTable = structure->copyPropertyTable();
     transition->m_isPinnedPropertyTable = true;
     
+    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
     return transition.release();
 }
 
     return transition.release();
 }
 
@@ -572,8 +535,7 @@ PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSObject* object)
         // in the order that they are expected to be in, but we need to
         // reorder the storage, so we have to copy the current values out
         Vector<JSValue> values(propertyCount);
         // in the order that they are expected to be in, but we need to
         // reorder the storage, so we have to copy the current values out
         Vector<JSValue> values(propertyCount);
-        // FIXME: Remove this workaround with the next merge.
-        unsigned anonymousSlotCount = 0;
+        unsigned anonymousSlotCount = m_anonymousSlotCount;
         for (unsigned i = 0; i < propertyCount; i++) {
             PropertyMapEntry* entry = sortedPropertyEntries[i];
             values[i] = object->getDirectOffset(entry->offset);
         for (unsigned i = 0; i < propertyCount; i++) {
             PropertyMapEntry* entry = sortedPropertyEntries[i];
             values[i] = object->getDirectOffset(entry->offset);
@@ -598,27 +560,32 @@ PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSObject* object)
 
 size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
 {
 
 size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
 {
-    ASSERT(!m_transitions.singleTransition);
+    ASSERT(!m_enumerationCache);
+
+    if (m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
+        specificValue = 0;
 
     materializePropertyMapIfNecessary();
 
     m_isPinnedPropertyTable = true;
 
     materializePropertyMapIfNecessary();
 
     m_isPinnedPropertyTable = true;
+
     size_t offset = put(propertyName, attributes, specificValue);
     size_t offset = put(propertyName, attributes, specificValue);
+    ASSERT(offset >= m_anonymousSlotCount);
     if (propertyStorageSize() > propertyStorageCapacity())
         growPropertyStorageCapacity();
     if (propertyStorageSize() > propertyStorageCapacity())
         growPropertyStorageCapacity();
-    clearEnumerationCache();
     return offset;
 }
 
 size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
 {
     ASSERT(isUncacheableDictionary());
     return offset;
 }
 
 size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
 {
     ASSERT(isUncacheableDictionary());
+    ASSERT(!m_enumerationCache);
 
     materializePropertyMapIfNecessary();
 
     m_isPinnedPropertyTable = true;
     size_t offset = remove(propertyName);
 
     materializePropertyMapIfNecessary();
 
     m_isPinnedPropertyTable = true;
     size_t offset = remove(propertyName);
-    clearEnumerationCache();
+    ASSERT(offset >= m_anonymousSlotCount);
     return offset;
 }
 
     return offset;
 }
 
@@ -684,7 +651,7 @@ size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& sp
     if (!m_propertyTable)
         return notFound;
 
     if (!m_propertyTable)
         return notFound;
 
-    unsigned i = rep->computedHash();
+    unsigned i = rep->existingHash();
 
 #if DUMP_PROPERTYMAP_STATS
     ++numProbes;
 
 #if DUMP_PROPERTYMAP_STATS
     ++numProbes;
@@ -697,6 +664,7 @@ size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& sp
     if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
         attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
         specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
     if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
         attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
         specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
+        ASSERT(m_propertyTable->entries()[entryIndex - 1].offset >= m_anonymousSlotCount);
         return m_propertyTable->entries()[entryIndex - 1].offset;
     }
 
         return m_propertyTable->entries()[entryIndex - 1].offset;
     }
 
@@ -704,7 +672,7 @@ size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& sp
     ++numCollisions;
 #endif
 
     ++numCollisions;
 #endif
 
-    unsigned k = 1 | doubleHash(rep->computedHash());
+    unsigned k = 1 | doubleHash(rep->existingHash());
 
     while (1) {
         i += k;
 
     while (1) {
         i += k;
@@ -720,6 +688,7 @@ size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& sp
         if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
             attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
             specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
         if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
             attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
             specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
+            ASSERT(m_propertyTable->entries()[entryIndex - 1].offset >= m_anonymousSlotCount);
             return m_propertyTable->entries()[entryIndex - 1].offset;
         }
     }
             return m_propertyTable->entries()[entryIndex - 1].offset;
         }
     }
@@ -735,7 +704,7 @@ bool Structure::despecifyFunction(const Identifier& propertyName)
 
     UString::Rep* rep = propertyName._ustring.rep();
 
 
     UString::Rep* rep = propertyName._ustring.rep();
 
-    unsigned i = rep->computedHash();
+    unsigned i = rep->existingHash();
 
 #if DUMP_PROPERTYMAP_STATS
     ++numProbes;
 
 #if DUMP_PROPERTYMAP_STATS
     ++numProbes;
@@ -755,7 +724,7 @@ bool Structure::despecifyFunction(const Identifier& propertyName)
     ++numCollisions;
 #endif
 
     ++numCollisions;
 #endif
 
-    unsigned k = 1 | doubleHash(rep->computedHash());
+    unsigned k = 1 | doubleHash(rep->existingHash());
 
     while (1) {
         i += k;
 
     while (1) {
         i += k;
@@ -776,6 +745,17 @@ bool Structure::despecifyFunction(const Identifier& propertyName)
     }
 }
 
     }
 }
 
+void Structure::despecifyAllFunctions()
+{
+    materializePropertyMapIfNecessary();
+    if (!m_propertyTable)
+        return;
+    
+    unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
+    for (unsigned i = 1; i <= entryCount; ++i)
+        m_propertyTable->entries()[i].specificValue = 0;
+}
+
 size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
 {
     ASSERT(!propertyName.isNull());
 size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
 {
     ASSERT(!propertyName.isNull());
@@ -783,6 +763,9 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel
 
     checkConsistency();
 
 
     checkConsistency();
 
+    if (attributes & DontEnum)
+        m_hasNonEnumerableProperties = true;
+
     UString::Rep* rep = propertyName._ustring.rep();
 
     if (!m_propertyTable)
     UString::Rep* rep = propertyName._ustring.rep();
 
     if (!m_propertyTable)
@@ -790,7 +773,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel
 
     // FIXME: Consider a fast case for tables with no deleted sentinels.
 
 
     // FIXME: Consider a fast case for tables with no deleted sentinels.
 
-    unsigned i = rep->computedHash();
+    unsigned i = rep->existingHash();
     unsigned k = 0;
     bool foundDeletedElement = false;
     unsigned deletedElementIndex = 0; // initialize to make the compiler happy
     unsigned k = 0;
     bool foundDeletedElement = false;
     unsigned deletedElementIndex = 0; // initialize to make the compiler happy
@@ -813,7 +796,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel
         }
 
         if (k == 0) {
         }
 
         if (k == 0) {
-            k = 1 | doubleHash(rep->computedHash());
+            k = 1 | doubleHash(rep->existingHash());
 #if DUMP_PROPERTYMAP_STATS
             ++numCollisions;
 #endif
 #if DUMP_PROPERTYMAP_STATS
             ++numCollisions;
 #endif
@@ -854,9 +837,10 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel
         newOffset = m_propertyTable->deletedOffsets->last();
         m_propertyTable->deletedOffsets->removeLast();
     } else
         newOffset = m_propertyTable->deletedOffsets->last();
         m_propertyTable->deletedOffsets->removeLast();
     } else
-        newOffset = m_propertyTable->keyCount;
+        newOffset = m_propertyTable->keyCount + m_anonymousSlotCount;
     m_propertyTable->entries()[entryIndex - 1].offset = newOffset;
     m_propertyTable->entries()[entryIndex - 1].offset = newOffset;
-
+    
+    ASSERT(newOffset >= m_anonymousSlotCount);
     ++m_propertyTable->keyCount;
 
     if ((m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount) * 2 >= m_propertyTable->size)
     ++m_propertyTable->keyCount;
 
     if ((m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount) * 2 >= m_propertyTable->size)
@@ -868,12 +852,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel
 
 bool Structure::hasTransition(UString::Rep* rep, unsigned attributes)
 {
 
 bool Structure::hasTransition(UString::Rep* rep, unsigned attributes)
 {
-    if (m_usingSingleTransitionSlot) {
-        return m_transitions.singleTransition
-            && m_transitions.singleTransition->m_nameInPrevious == rep
-            && m_transitions.singleTransition->m_attributesInPrevious == attributes;
-    }
-    return m_transitions.table->hasTransition(make_pair(rep, attributes));
+    return table.hasTransition(make_pair(rep, attributes));
 }
 
 size_t Structure::remove(const Identifier& propertyName)
 }
 
 size_t Structure::remove(const Identifier& propertyName)
@@ -893,7 +872,7 @@ size_t Structure::remove(const Identifier& propertyName)
 #endif
 
     // Find the thing to remove.
 #endif
 
     // Find the thing to remove.
-    unsigned i = rep->computedHash();
+    unsigned i = rep->existingHash();
     unsigned k = 0;
     unsigned entryIndex;
     UString::Rep* key = 0;
     unsigned k = 0;
     unsigned entryIndex;
     UString::Rep* key = 0;
@@ -907,7 +886,7 @@ size_t Structure::remove(const Identifier& propertyName)
             break;
 
         if (k == 0) {
             break;
 
         if (k == 0) {
-            k = 1 | doubleHash(rep->computedHash());
+            k = 1 | doubleHash(rep->existingHash());
 #if DUMP_PROPERTYMAP_STATS
             ++numCollisions;
 #endif
 #if DUMP_PROPERTYMAP_STATS
             ++numCollisions;
 #endif
@@ -925,6 +904,7 @@ size_t Structure::remove(const Identifier& propertyName)
     m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = deletedSentinelIndex;
 
     size_t offset = m_propertyTable->entries()[entryIndex - 1].offset;
     m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = deletedSentinelIndex;
 
     size_t offset = m_propertyTable->entries()[entryIndex - 1].offset;
+    ASSERT(offset >= m_anonymousSlotCount);
 
     key->deref();
     m_propertyTable->entries()[entryIndex - 1].key = 0;
 
     key->deref();
     m_propertyTable->entries()[entryIndex - 1].key = 0;
@@ -950,8 +930,8 @@ size_t Structure::remove(const Identifier& propertyName)
 void Structure::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry)
 {
     ASSERT(m_propertyTable);
 void Structure::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry)
 {
     ASSERT(m_propertyTable);
-
-    unsigned i = entry.key->computedHash();
+    ASSERT(entry.offset >= m_anonymousSlotCount);
+    unsigned i = entry.key->existingHash();
     unsigned k = 0;
 
 #if DUMP_PROPERTYMAP_STATS
     unsigned k = 0;
 
 #if DUMP_PROPERTYMAP_STATS
@@ -964,7 +944,7 @@ void Structure::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry)
             break;
 
         if (k == 0) {
             break;
 
         if (k == 0) {
-            k = 1 | doubleHash(entry.key->computedHash());
+            k = 1 | doubleHash(entry.key->existingHash());
 #if DUMP_PROPERTYMAP_STATS
             ++numCollisions;
 #endif
 #if DUMP_PROPERTYMAP_STATS
             ++numCollisions;
 #endif
@@ -1057,7 +1037,7 @@ int comparePropertyMapEntryIndices(const void* a, const void* b)
     return 0;
 }
 
     return 0;
 }
 
-void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyNames)
+void Structure::getPropertyNames(PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     materializePropertyMapIfNecessary();
     if (!m_propertyTable)
 {
     materializePropertyMapIfNecessary();
     if (!m_propertyTable)
@@ -1068,7 +1048,8 @@ void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyN
         int i = 0;
         unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
         for (unsigned k = 1; k <= entryCount; k++) {
         int i = 0;
         unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
         for (unsigned k = 1; k <= entryCount; k++) {
-            if (m_propertyTable->entries()[k].key && !(m_propertyTable->entries()[k].attributes & DontEnum)) {
+            ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[k].attributes & DontEnum));
+            if (m_propertyTable->entries()[k].key && (!(m_propertyTable->entries()[k].attributes & DontEnum) || (mode == IncludeDontEnumProperties))) {
                 PropertyMapEntry* value = &m_propertyTable->entries()[k];
                 int j;
                 for (j = i - 1; j >= 0 && a[j]->index > value->index; --j)
                 PropertyMapEntry* value = &m_propertyTable->entries()[k];
                 int j;
                 for (j = i - 1; j >= 0 && a[j]->index > value->index; --j)
@@ -1095,7 +1076,7 @@ void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyN
     PropertyMapEntry** p = sortedEnumerables.data();
     unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
     for (unsigned i = 1; i <= entryCount; i++) {
     PropertyMapEntry** p = sortedEnumerables.data();
     unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
     for (unsigned i = 1; i <= entryCount; i++) {
-        if (m_propertyTable->entries()[i].key && !(m_propertyTable->entries()[i].attributes & DontEnum))
+        if (m_propertyTable->entries()[i].key && (!(m_propertyTable->entries()[i].attributes & DontEnum) || (mode == IncludeDontEnumProperties)))
             *p++ = &m_propertyTable->entries()[i];
     }
 
             *p++ = &m_propertyTable->entries()[i];
     }
 
@@ -1114,25 +1095,6 @@ void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyN
     }
 }
 
     }
 }
 
-void Structure::getEnumerableNamesFromClassInfoTable(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames)
-{
-    // Add properties from the static hashtables of properties
-    for (; classInfo; classInfo = classInfo->parentClass) {
-        const HashTable* table = classInfo->propHashTable(exec);
-        if (!table)
-            continue;
-        table->initializeIfNeeded(exec);
-        ASSERT(table->table);
-
-        int hashSizeMask = table->compactSize - 1;
-        const HashEntry* entry = table->table;
-        for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
-            if (entry->key() && !(entry->attributes() & DontEnum))
-                propertyNames.add(entry->key());
-        }
-    }
-}
-
 #if DO_PROPERTYMAP_CONSTENCY_CHECK
 
 void Structure::checkConsistency()
 #if DO_PROPERTYMAP_CONSTENCY_CHECK
 
 void Structure::checkConsistency()
@@ -1174,11 +1136,13 @@ void Structure::checkConsistency()
 
     unsigned nonEmptyEntryCount = 0;
     for (unsigned c = 1; c <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; ++c) {
 
     unsigned nonEmptyEntryCount = 0;
     for (unsigned c = 1; c <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; ++c) {
+        ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[c].attributes & DontEnum));
         UString::Rep* rep = m_propertyTable->entries()[c].key;
         UString::Rep* rep = m_propertyTable->entries()[c].key;
+        ASSERT(m_propertyTable->entries()[c].offset >= m_anonymousSlotCount);
         if (!rep)
             continue;
         ++nonEmptyEntryCount;
         if (!rep)
             continue;
         ++nonEmptyEntryCount;
-        unsigned i = rep->computedHash();
+        unsigned i = rep->existingHash();
         unsigned k = 0;
         unsigned entryIndex;
         while (1) {
         unsigned k = 0;
         unsigned entryIndex;
         while (1) {
@@ -1187,7 +1151,7 @@ void Structure::checkConsistency()
             if (rep == m_propertyTable->entries()[entryIndex - 1].key)
                 break;
             if (k == 0)
             if (rep == m_propertyTable->entries()[entryIndex - 1].key)
                 break;
             if (k == 0)
-                k = 1 | doubleHash(rep->computedHash());
+                k = 1 | doubleHash(rep->existingHash());
             i += k;
         }
         ASSERT(entryIndex == c + 1);
             i += k;
         }
         ASSERT(entryIndex == c + 1);
index 55b7186089dc7b2c6ddc1ef0a1aa71c11c4cdbcd..451ba3cefe3f5c030ed4e6a01a6e0838d699966e 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "JSType.h"
 #include "JSValue.h"
 #include "PropertyMapHashTable.h"
 #include "JSType.h"
 #include "JSValue.h"
 #include "PropertyMapHashTable.h"
+#include "PropertyNameArray.h"
+#include "Protect.h"
 #include "StructureChain.h"
 #include "StructureTransitionTable.h"
 #include "StructureChain.h"
 #include "StructureTransitionTable.h"
-#include "TypeInfo.h"
+#include "JSTypeInfo.h"
 #include "UString.h"
 #include "UString.h"
+#include "WeakGCPtr.h"
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 
 
 namespace JSC {
 
 
 namespace JSC {
 
+    class MarkStack;
     class PropertyNameArray;
     class PropertyNameArrayData;
 
     class PropertyNameArray;
     class PropertyNameArrayData;
 
+    enum EnumerationMode {
+        ExcludeDontEnumProperties,
+        IncludeDontEnumProperties
+    };
+
     class Structure : public RefCounted<Structure> {
     public:
         friend class JIT;
     class Structure : public RefCounted<Structure> {
     public:
         friend class JIT;
-        static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo)
+        friend class StructureTransitionTable;
+        static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
         {
         {
-            return adoptRef(new Structure(prototype, typeInfo));
+            return adoptRef(new Structure(prototype, typeInfo, anonymousSlotCount));
         }
 
         static void startIgnoringLeaks();
         }
 
         static void startIgnoringLeaks();
@@ -65,7 +75,7 @@ namespace JSC {
         static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
         static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset);
         static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype);
         static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
         static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset);
         static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype);
-        static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&);        
+        static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&);
         static PassRefPtr<Structure> getterSetterTransition(Structure*);
         static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*);
         static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*);
         static PassRefPtr<Structure> getterSetterTransition(Structure*);
         static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*);
         static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*);
@@ -74,12 +84,6 @@ namespace JSC {
 
         ~Structure();
 
 
         ~Structure();
 
-        void mark()
-        {
-            if (!m_prototype.marked())
-                m_prototype.mark();
-        }
-
         // These should be used with caution.  
         size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
         size_t removePropertyWithoutTransition(const Identifier& propertyName);
         // These should be used with caution.  
         size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
         size_t removePropertyWithoutTransition(const Identifier& propertyName);
@@ -97,8 +101,8 @@ namespace JSC {
         Structure* previousID() const { return m_previous.get(); }
 
         void growPropertyStorageCapacity();
         Structure* previousID() const { return m_previous.get(); }
 
         void growPropertyStorageCapacity();
-        size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; }
-        size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; }
+        unsigned propertyStorageCapacity() const { return m_propertyStorageCapacity; }
+        unsigned propertyStorageSize() const { return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1); }
         bool isUsingInlineStorage() const;
 
         size_t get(const Identifier& propertyName);
         bool isUsingInlineStorage() const;
 
         size_t get(const Identifier& propertyName);
@@ -118,18 +122,27 @@ namespace JSC {
             return hasTransition(propertyName._ustring.rep(), attributes);
         }
 
             return hasTransition(propertyName._ustring.rep(), attributes);
         }
 
-        void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
-
         bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
         void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
 
         bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
         void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
 
+        bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
+
+        bool hasAnonymousSlots() const { return !!m_anonymousSlotCount; }
+        unsigned anonymousSlotCount() const { return m_anonymousSlotCount; }
+        
         bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; }
 
         bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; }
 
-        JSCell* specificValue() { return m_specificValueInPrevious; }
         void despecifyDictionaryFunction(const Identifier& propertyName);
         void despecifyDictionaryFunction(const Identifier& propertyName);
+        void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
 
 
+        void setEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
+        void clearEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
+        JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
+        void getPropertyNames(PropertyNameArray&, EnumerationMode mode);
+        
     private:
     private:
-        Structure(JSValue prototype, const TypeInfo&);
+
+        Structure(JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount);
         
         typedef enum { 
             NoneDictionaryKind = 0,
         
         typedef enum { 
             NoneDictionaryKind = 0,
@@ -140,8 +153,6 @@ namespace JSC {
 
         size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
         size_t remove(const Identifier& propertyName);
 
         size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
         size_t remove(const Identifier& propertyName);
-        void getEnumerableNamesFromPropertyTable(PropertyNameArray&);
-        void getEnumerableNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&);
 
         void expandPropertyMapHashTable();
         void rehashPropertyMapHashTable();
 
         void expandPropertyMapHashTable();
         void rehashPropertyMapHashTable();
@@ -152,6 +163,7 @@ namespace JSC {
         void checkConsistency();
 
         bool despecifyFunction(const Identifier&);
         void checkConsistency();
 
         bool despecifyFunction(const Identifier&);
+        void despecifyAllFunctions();
 
         PropertyMapHashTable* copyPropertyTable();
         void materializePropertyMap();
 
         PropertyMapHashTable* copyPropertyTable();
         void materializePropertyMap();
@@ -162,8 +174,6 @@ namespace JSC {
             materializePropertyMap();
         }
 
             materializePropertyMap();
         }
 
-        void clearEnumerationCache();
-
         signed char transitionCount() const
         {
             // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
         signed char transitionCount() const
         {
             // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
@@ -178,6 +188,8 @@ namespace JSC {
 
         static const signed char noOffset = -1;
 
 
         static const signed char noOffset = -1;
 
+        static const unsigned maxSpecificFunctionThrashCount = 3;
+
         TypeInfo m_typeInfo;
 
         JSValue m_prototype;
         TypeInfo m_typeInfo;
 
         JSValue m_prototype;
@@ -187,23 +199,32 @@ namespace JSC {
         RefPtr<UString::Rep> m_nameInPrevious;
         JSCell* m_specificValueInPrevious;
 
         RefPtr<UString::Rep> m_nameInPrevious;
         JSCell* m_specificValueInPrevious;
 
-        union {
-            Structure* singleTransition;
-            StructureTransitionTable* table;
-        } m_transitions;
+        StructureTransitionTable table;
 
 
-        RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;
+        WeakGCPtr<JSPropertyNameIterator> m_enumerationCache;
 
         PropertyMapHashTable* m_propertyTable;
 
 
         PropertyMapHashTable* m_propertyTable;
 
-        size_t m_propertyStorageCapacity;
+        uint32_t m_propertyStorageCapacity;
+
+        // m_offset does not account for anonymous slots
         signed char m_offset;
 
         unsigned m_dictionaryKind : 2;
         bool m_isPinnedPropertyTable : 1;
         bool m_hasGetterSetterProperties : 1;
         signed char m_offset;
 
         unsigned m_dictionaryKind : 2;
         bool m_isPinnedPropertyTable : 1;
         bool m_hasGetterSetterProperties : 1;
-        bool m_usingSingleTransitionSlot : 1;
+        bool m_hasNonEnumerableProperties : 1;
+#if COMPILER(WINSCW)
+        // Workaround for Symbian WINSCW compiler that cannot resolve unsigned type of the declared 
+        // bitfield, when used as argument in make_pair() function calls in structure.ccp.
+        // This bitfield optimization is insignificant for the Symbian emulator target.
+        unsigned m_attributesInPrevious;
+#else
         unsigned m_attributesInPrevious : 7;
         unsigned m_attributesInPrevious : 7;
+#endif
+        unsigned m_specificFunctionThrashCount : 2;
+        unsigned m_anonymousSlotCount : 5;
+        // 5 free bits
     };
 
     inline size_t Structure::get(const Identifier& propertyName)
     };
 
     inline size_t Structure::get(const Identifier& propertyName)
@@ -216,7 +237,7 @@ namespace JSC {
 
         UString::Rep* rep = propertyName._ustring.rep();
 
 
         UString::Rep* rep = propertyName._ustring.rep();
 
-        unsigned i = rep->computedHash();
+        unsigned i = rep->existingHash();
 
 #if DUMP_PROPERTYMAP_STATS
         ++numProbes;
 
 #if DUMP_PROPERTYMAP_STATS
         ++numProbes;
@@ -233,7 +254,7 @@ namespace JSC {
         ++numCollisions;
 #endif
 
         ++numCollisions;
 #endif
 
-        unsigned k = 1 | WTF::doubleHash(rep->computedHash());
+        unsigned k = 1 | WTF::doubleHash(rep->existingHash());
 
         while (1) {
             i += k;
 
         while (1) {
             i += k;
@@ -253,8 +274,14 @@ namespace JSC {
     
     bool StructureTransitionTable::contains(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
     {
     
     bool StructureTransitionTable::contains(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
     {
-        TransitionTable::iterator find = m_table.find(key);
-        if (find == m_table.end())
+        if (usingSingleTransitionSlot()) {
+            Structure* existingTransition = singleTransition();
+            return existingTransition && existingTransition->m_nameInPrevious.get() == key.first
+                   && existingTransition->m_attributesInPrevious == key.second
+                   && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0);
+        }
+        TransitionTable::iterator find = table()->find(key);
+        if (find == table()->end())
             return false;
 
         return find->second.first || find->second.second->transitionedFor(specificValue);
             return false;
 
         return find->second.first || find->second.second->transitionedFor(specificValue);
@@ -262,11 +289,40 @@ namespace JSC {
 
     Structure* StructureTransitionTable::get(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const
     {
 
     Structure* StructureTransitionTable::get(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const
     {
-        Transition transition = m_table.get(key);
+        if (usingSingleTransitionSlot()) {
+            Structure* existingTransition = singleTransition();
+            if (existingTransition && existingTransition->m_nameInPrevious.get() == key.first
+                && existingTransition->m_attributesInPrevious == key.second
+                && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0))
+                return existingTransition;
+            return 0;
+        }
+
+        Transition transition = table()->get(key);
         if (transition.second && transition.second->transitionedFor(specificValue))
             return transition.second;
         return transition.first;
     }
         if (transition.second && transition.second->transitionedFor(specificValue))
             return transition.second;
         return transition.first;
     }
+
+    bool StructureTransitionTable::hasTransition(const StructureTransitionTableHash::Key& key) const
+    {
+        if (usingSingleTransitionSlot()) {
+            Structure* transition = singleTransition();
+            return transition && transition->m_nameInPrevious == key.first
+            && transition->m_attributesInPrevious == key.second;
+        }
+        return table()->contains(key);
+    }
+    
+    void StructureTransitionTable::reifySingleTransition()
+    {
+        ASSERT(usingSingleTransitionSlot());
+        Structure* existingTransition = singleTransition();
+        TransitionTable* transitionTable = new TransitionTable;
+        setTransitionTable(transitionTable);
+        if (existingTransition)
+            add(std::make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious);
+    }
 } // namespace JSC
 
 #endif // Structure_h
 } // namespace JSC
 
 #endif // Structure_h
index e83f626ab1b134be7e397dcf73092d03ce573273..085876c496b54ea5d5f0a072b1f07fd88677e65d 100644 (file)
@@ -46,16 +46,4 @@ StructureChain::StructureChain(Structure* head)
     m_vector[i] = 0;
 }
 
     m_vector[i] = 0;
 }
 
-bool StructureChain::isCacheable() const
-{
-    uint32_t i = 0;
-    
-    while (m_vector[i]) {
-        // Both classes of dictionary structure may change arbitrarily so we can't cache them
-        if (m_vector[i++]->isDictionary())
-            return false;
-    }
-    return true;
-}
-
 } // namespace JSC
 } // namespace JSC
index c48749d29be302f6733162ec4c972b2c4e5340b7..816b66d5051550bceb2b4efa27e51419e2d9a33f 100644 (file)
@@ -36,10 +36,11 @@ namespace JSC {
     class Structure;
 
     class StructureChain : public RefCounted<StructureChain> {
     class Structure;
 
     class StructureChain : public RefCounted<StructureChain> {
+        friend class JIT;
+
     public:
         static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); }
         RefPtr<Structure>* head() { return m_vector.get(); }
     public:
         static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); }
         RefPtr<Structure>* head() { return m_vector.get(); }
-        bool isCacheable() const;
 
     private:
         StructureChain(Structure* head);
 
     private:
         StructureChain(Structure* head);
index 5b4f4e63221b83043fd78e7cd167e723cdced22a..320dbddc9a41eb627c60ccde75459ecd086df777 100644 (file)
@@ -30,6 +30,8 @@
 #include <wtf/HashFunctions.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashTraits.h>
 #include <wtf/HashFunctions.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashTraits.h>
+#include <wtf/PtrAndFlags.h>
+#include <wtf/OwnPtr.h>
 #include <wtf/RefPtr.h>
 
 namespace JSC {
 #include <wtf/RefPtr.h>
 
 namespace JSC {
@@ -40,7 +42,7 @@ namespace JSC {
         typedef std::pair<RefPtr<UString::Rep>, unsigned> Key;
         static unsigned hash(const Key& p)
         {
         typedef std::pair<RefPtr<UString::Rep>, unsigned> Key;
         static unsigned hash(const Key& p)
         {
-            return p.first->computedHash();
+            return p.first->existingHash();
         }
 
         static bool equal(const Key& a, const Key& b)
         }
 
         static bool equal(const Key& a, const Key& b)
@@ -69,43 +71,93 @@ namespace JSC {
         typedef std::pair<Structure*, Structure*> Transition;
         typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable;
     public:
         typedef std::pair<Structure*, Structure*> Transition;
         typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable;
     public:
+        StructureTransitionTable() {
+            m_transitions.m_singleTransition.set(0);
+            m_transitions.m_singleTransition.setFlag(usingSingleSlot);
+        }
+
+        ~StructureTransitionTable() {
+            if (!usingSingleTransitionSlot())
+                delete table();
+        }
+
         // The contains and get methods accept imprecise matches, so if an unspecialised transition exists
         // for the given key they will consider that transition to be a match.  If a specialised transition
         // exists and it matches the provided specificValue, get will return the specific transition.
         inline bool contains(const StructureTransitionTableHash::Key&, JSCell* specificValue);
         inline Structure* get(const StructureTransitionTableHash::Key&, JSCell* specificValue) const;
         // The contains and get methods accept imprecise matches, so if an unspecialised transition exists
         // for the given key they will consider that transition to be a match.  If a specialised transition
         // exists and it matches the provided specificValue, get will return the specific transition.
         inline bool contains(const StructureTransitionTableHash::Key&, JSCell* specificValue);
         inline Structure* get(const StructureTransitionTableHash::Key&, JSCell* specificValue) const;
-        bool hasTransition(const StructureTransitionTableHash::Key& key)
-        {
-            return m_table.contains(key);
-        }
+        inline bool hasTransition(const StructureTransitionTableHash::Key& key) const;
         void remove(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
         {
         void remove(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
         {
-            TransitionTable::iterator find = m_table.find(key);
+            if (usingSingleTransitionSlot()) {
+                ASSERT(contains(key, specificValue));
+                setSingleTransition(0);
+                return;
+            }
+            TransitionTable::iterator find = table()->find(key);
             if (!specificValue)
                 find->second.first = 0;
             else
                 find->second.second = 0;
             if (!find->second.first && !find->second.second)
             if (!specificValue)
                 find->second.first = 0;
             else
                 find->second.second = 0;
             if (!find->second.first && !find->second.second)
-                m_table.remove(find);
+                table()->remove(find);
         }
         void add(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue)
         {
         }
         void add(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue)
         {
+            if (usingSingleTransitionSlot()) {
+                if (!singleTransition()) {
+                    setSingleTransition(structure);
+                    return;
+                }
+                reifySingleTransition();
+            }
             if (!specificValue) {
             if (!specificValue) {
-                TransitionTable::iterator find = m_table.find(key);
-                if (find == m_table.end())
-                    m_table.add(key, Transition(structure, 0));
+                TransitionTable::iterator find = table()->find(key);
+                if (find == table()->end())
+                    table()->add(key, Transition(structure, 0));
                 else
                     find->second.first = structure;
             } else {
                 // If we're adding a transition to a specific value, then there cannot be
                 // an existing transition
                 else
                     find->second.first = structure;
             } else {
                 // If we're adding a transition to a specific value, then there cannot be
                 // an existing transition
-                ASSERT(!m_table.contains(key));
-                m_table.add(key, Transition(0, structure));
+                ASSERT(!table()->contains(key));
+                table()->add(key, Transition(0, structure));
             }
             }
-
         }
         }
+
     private:
     private:
-        TransitionTable m_table;
+        TransitionTable* table() const { ASSERT(!usingSingleTransitionSlot()); return m_transitions.m_table; }
+        Structure* singleTransition() const {
+            ASSERT(usingSingleTransitionSlot());
+            return m_transitions.m_singleTransition.get();
+        }
+        bool usingSingleTransitionSlot() const { return m_transitions.m_singleTransition.isFlagSet(usingSingleSlot); }
+        void setSingleTransition(Structure* structure)
+        { 
+            ASSERT(usingSingleTransitionSlot());
+            m_transitions.m_singleTransition.set(structure);
+        }
+
+        void setTransitionTable(TransitionTable* table)
+        {
+            ASSERT(usingSingleTransitionSlot());
+#ifndef NDEBUG
+            setSingleTransition(0);
+#endif
+            m_transitions.m_table = table;
+            // This implicitly clears the flag that indicates we're using a single transition
+            ASSERT(!usingSingleTransitionSlot());
+        }
+        inline void reifySingleTransition();
+
+        enum UsingSingleSlot {
+            usingSingleSlot
+        };
+        // Last bit indicates whether we are using the single transition optimisation
+        union {
+            TransitionTable* m_table;
+            PtrAndFlagsBase<Structure, UsingSingleSlot> m_singleTransition;
+        } m_transitions;
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index c00f95ab67668a5510064ce682820427736e2aac..f5e266960d61840d71f92cfe1e1e2089b3b026b0 100644 (file)
@@ -121,6 +121,10 @@ namespace JSC {
 
     typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
 
 
     typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
 
+    class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable>
+    {
+    };
+    
 } // namespace JSC
 
 #endif // SymbolTable_h
 } // namespace JSC
 
 #endif // SymbolTable_h
index 75bf37fa874128762d05253fd6d04bbc8bbc0621..77dfdfc40bd081105baa3d231daec621a9d77226 100644 (file)
 #include "CallFrame.h"
 #include "JSGlobalObject.h"
 
 #include "CallFrame.h"
 #include "JSGlobalObject.h"
 
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 #include <mach/mach.h>
 #include <mach/mach.h>
-#endif
-
-#if HAVE(SYS_TIME_H)
-#include <sys/time.h>
-#endif
-
-#if PLATFORM(WIN_OS)
+#elif OS(WINDOWS)
 #include <windows.h>
 #include <windows.h>
+#else
+#include "CurrentTime.h"
 #endif
 
 #endif
 
-#if PLATFORM(QT)
-#include <QDateTime>
+#if PLATFORM(BREWMP)
+#include <AEEStdLib.h>
 #endif
 
 using namespace std;
 #endif
 
 using namespace std;
@@ -62,7 +58,7 @@ static const int intervalBetweenChecks = 1000;
 // Returns the time the current thread has spent executing, in milliseconds.
 static inline unsigned getCPUTime()
 {
 // Returns the time the current thread has spent executing, in milliseconds.
 static inline unsigned getCPUTime()
 {
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
     mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
     thread_basic_info_data_t info;
 
     mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
     thread_basic_info_data_t info;
 
@@ -75,15 +71,7 @@ static inline unsigned getCPUTime()
     time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
     
     return time;
     time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
     
     return time;
-#elif HAVE(SYS_TIME_H)
-    // FIXME: This should probably use getrusage with the RUSAGE_THREAD flag.
-    struct timeval tv;
-    gettimeofday(&tv, 0);
-    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
-#elif PLATFORM(QT)
-    QDateTime t = QDateTime::currentDateTime();
-    return t.toTime_t() * 1000 + t.time().msec();
-#elif PLATFORM(WIN_OS)
+#elif OS(WINDOWS)
     union {
         FILETIME fileTime;
         unsigned long long fileTimeAsLong;
     union {
         FILETIME fileTime;
         unsigned long long fileTimeAsLong;
@@ -96,8 +84,14 @@ static inline unsigned getCPUTime()
     GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
     
     return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
     GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
     
     return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
+#elif PLATFORM(BREWMP)
+    // This function returns a continuously and linearly increasing millisecond
+    // timer from the time the device was powered on.
+    // There is only one thread in BREW, so this is enough.
+    return GETUPTIMEMS();
 #else
 #else
-#error Platform does not have getCurrentTime function
+    // FIXME: We should return the time the current thread has spent executing.
+    return currentTime() * 1000;
 #endif
 }
 
 #endif
 }
 
index b9efaffa11b4666014174dfd1ed807eb8b9d1b69..da854b99090ccd6594e2d8b789f1e146baa07454 100644 (file)
@@ -27,7 +27,7 @@ provider JavaScriptCore
 {
     probe gc__begin();
     probe gc__marked();
 {
     probe gc__begin();
     probe gc__marked();
-    probe gc__end(int, int);
+    probe gc__end();
     
     probe profile__will_execute(int, char*, char*, int);
     probe profile__did_execute(int, char*, char*, int);
     
     probe profile__will_execute(int, char*, char*, int);
     probe profile__did_execute(int, char*, char*, int);
index e544f66926b79c4df5a3b7cebcf883d245485c70..c28c85f614270e44ea6a9da96c541390d8602a6c 100644 (file)
@@ -33,7 +33,7 @@
 #define JAVASCRIPTCORE_GC_BEGIN()
 #define JAVASCRIPTCORE_GC_BEGIN_ENABLED() 0
 
 #define JAVASCRIPTCORE_GC_BEGIN()
 #define JAVASCRIPTCORE_GC_BEGIN_ENABLED() 0
 
-#define JAVASCRIPTCORE_GC_END(arg0, arg1)
+#define JAVASCRIPTCORE_GC_END()
 #define JAVASCRIPTCORE_GC_END_ENABLED() 0
 
 #define JAVASCRIPTCORE_GC_MARKED()
 #define JAVASCRIPTCORE_GC_END_ENABLED() 0
 
 #define JAVASCRIPTCORE_GC_MARKED()
diff --git a/runtime/TypeInfo.h b/runtime/TypeInfo.h
deleted file mode 100644 (file)
index 70aeed3..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// -*- 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 ImplementsDefaultHasInstance = 1 << 3;
-    static const unsigned NeedsThisConversion = 1 << 4;
-    static const unsigned HasStandardGetOwnPropertySlot = 1 << 5;
-
-    class TypeInfo {
-        friend class JIT;
-    public:
-        TypeInfo(JSType type, unsigned flags = 0)
-            : m_type(type)
-        {
-            // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance)
-            if ((flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
-                m_flags = flags | ImplementsDefaultHasInstance;
-            else
-                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
index e1e51df55f524b44102559abd394fa0d62b471d6..8b11b37d4a3a6575ad0d10f482702832bf26c743 100644 (file)
 #include "Identifier.h"
 #include "Operations.h"
 #include <ctype.h>
 #include "Identifier.h"
 #include "Operations.h"
 #include <ctype.h>
-#include <float.h>
 #include <limits.h>
 #include <limits.h>
+#include <limits>
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/Assertions.h>
 #include <wtf/MathExtras.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/Assertions.h>
 #include <wtf/MathExtras.h>
+#include <wtf/StringExtras.h>
 #include <wtf/Vector.h>
 #include <wtf/unicode/UTF8.h>
 #include <wtf/Vector.h>
 #include <wtf/unicode/UTF8.h>
+#include <wtf/StringExtras.h>
 
 
-#if HAVE(STRING_H)
-#include <string.h>
-#endif
 #if HAVE(STRINGS_H)
 #include <strings.h>
 #endif
 #if HAVE(STRINGS_H)
 #include <strings.h>
 #endif
@@ -52,52 +52,11 @@ using namespace WTF;
 using namespace WTF::Unicode;
 using namespace std;
 
 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;
 
 namespace JSC {
  
 extern const double NaN;
 extern const double Inf;
 
-// This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings.
-static const int minLengthToShare = 10;
-
-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])
 CString::CString(const char* c)
     : m_length(strlen(c))
     , m_data(new char[m_length + 1])
@@ -190,391 +149,52 @@ bool operator==(const CString& c1, const CString& c2)
 // 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;
 // 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::BaseString* UString::Rep::nullBaseString;
-UString::BaseString* UString::Rep::emptyBaseString;
+UStringImpl* UStringImpl::s_null;
+UStringImpl* UStringImpl::s_empty;
 UString* UString::nullUString;
 
 UString* UString::nullUString;
 
-static void initializeStaticBaseString(UString::BaseString& base)
-{
-    base.rc = INT_MAX / 2;
-    base.m_identifierTableAndFlags.setFlag(UString::Rep::StaticFlag);
-    base.checkConsistency();
-}
-
 void initializeUString()
 {
 void initializeUString()
 {
-    UString::Rep::nullBaseString = new UString::BaseString(0, 0);
-    initializeStaticBaseString(*UString::Rep::nullBaseString);
-
-    UString::Rep::emptyBaseString = new UString::BaseString(&sharedEmptyChar, 0);
-    initializeStaticBaseString(*UString::Rep::emptyBaseString);
-
+    UStringImpl::s_null = new UStringImpl(0, 0, UStringImpl::ConstructStaticString);
+    UStringImpl::s_empty = new UStringImpl(&sharedEmptyChar, 0, UStringImpl::ConstructStaticString);
     UString::nullUString = new UString;
 }
 
     UString::nullUString = new UString;
 }
 
-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::createFromUTF8(const char* string)
+static PassRefPtr<UString::Rep> createRep(const char* c)
 {
 {
-    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))
+    if (!c)
         return &UString::Rep::null();
 
         return &UString::Rep::null();
 
-    return UString::Rep::createCopying(buffer.data(), p - buffer.data());
-}
-
-PassRefPtr<UString::Rep> UString::Rep::create(UChar* string, int length, PassRefPtr<UString::SharedUChar> sharedBuffer)
-{
-    PassRefPtr<UString::Rep> rep = create(string, length);
-    rep->baseString()->setSharedBuffer(sharedBuffer);
-    rep->checkConsistency();
-    return rep;
-}
-
-UString::SharedUChar* UString::Rep::sharedBuffer()
-{
-    UString::BaseString* base = baseString();
-    if (len < minLengthToShare)
-        return 0;
-
-    return base->sharedBuffer();
-}
-
-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);
-
-        UString::BaseString* base = baseString();
-        if (base == this) {
-            if (m_sharedBuffer)
-                m_sharedBuffer->deref();
-            else
-                fastFree(base->buf);
-        } else
-            base->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
-{
-    const UString::BaseString* base = baseString();
-
-    // There is no recursion for base strings.
-    ASSERT(base == base->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(base->usedPreCapacity <= base->preCapacity);
-    ASSERT(base->usedCapacity <= base->capacity);
-    ASSERT(-offset <= base->usedPreCapacity);
-    ASSERT(offset + len <= base->usedCapacity);
-}
-#endif
-
-UString::SharedUChar* UString::BaseString::sharedBuffer()
-{
-    if (!m_sharedBuffer)
-        setSharedBuffer(SharedUChar::create(new OwnFastMallocPtr<UChar>(buf)));
-    return m_sharedBuffer;
-}
-
-void UString::BaseString::setSharedBuffer(PassRefPtr<UString::SharedUChar> sharedBuffer)
-{
-    // The manual steps below are because m_sharedBuffer can't be a RefPtr. m_sharedBuffer
-    // is in a union with another variable to avoid making BaseString any larger.
-    if (m_sharedBuffer)
-        m_sharedBuffer->deref();
-    m_sharedBuffer = sharedBuffer.releaseRef();
-}
-
-bool UString::BaseString::slowIsBufferReadOnly()
-{
-    // The buffer may not be modified as soon as the underlying data has been shared with another class.
-    if (m_sharedBuffer->isShared())
-        return true;
-
-    // At this point, we know it that the underlying buffer isn't shared outside of this base class,
-    // so get rid of m_sharedBuffer.
-    OwnPtr<OwnFastMallocPtr<UChar> > mallocPtr(m_sharedBuffer->release());
-    UChar* unsharedBuf = const_cast<UChar*>(mallocPtr->release());
-    setSharedBuffer(0);
-    preCapacity += (buf - unsharedBuf);
-    buf = unsharedBuf;
-    return false;
-}
-
-// Put these early so they can be inlined.
-static inline size_t expandedSize(size_t capacitySize, size_t precapacitySize)
-{
-    // Combine capacitySize & precapacitySize to produce a single size to allocate,
-    // check that doing so does not result in overflow.
-    size_t size = capacitySize + precapacitySize;
-    if (size < capacitySize)
-        return overflowIndicator();
-
-    // Small Strings (up to 4 pages):
-    // Expand the allocation size to 112.5% of the amount requested.  This is largely sicking
-    // to our previous policy, however 112.5% is cheaper to calculate.
-    if (size < 0x4000) {
-        size_t expandedSize = ((size + (size >> 3)) | 15) + 1;
-        // Given the limited range within which we calculate the expansion in this
-        // fashion the above calculation should never overflow.
-        ASSERT(expandedSize >= size);
-        ASSERT(expandedSize < maxUChars());
-        return expandedSize;
-    }
-
-    // Medium Strings (up to 128 pages):
-    // For pages covering multiple pages over-allocation is less of a concern - any unused
-    // space will not be paged in if it is not used, so this is purely a VM overhead.  For
-    // these strings allocate 2x the requested size.
-    if (size < 0x80000) {
-        size_t expandedSize = ((size + size) | 0xfff) + 1;
-        // Given the limited range within which we calculate the expansion in this
-        // fashion the above calculation should never overflow.
-        ASSERT(expandedSize >= size);
-        ASSERT(expandedSize < maxUChars());
-        return expandedSize;
-    }
-
-    // Large Strings (to infinity and beyond!):
-    // Revert to our 112.5% policy - probably best to limit the amount of unused VM we allow
-    // any individual string be responsible for.
-    size_t expandedSize = ((size + (size >> 3)) | 0xfff) + 1;
-
-    // Check for overflow - any result that is at least as large as requested (but
-    // still below the limit) is okay.
-    if ((expandedSize >= size) && (expandedSize < maxUChars()))
-        return expandedSize;
-    return overflowIndicator();
-}
-
-static inline bool expandCapacity(UString::Rep* rep, int requiredLength)
-{
-    rep->checkConsistency();
-    ASSERT(!rep->baseString()->isBufferReadOnly());
-
-    UString::BaseString* base = rep->baseString();
-
-    if (requiredLength > base->capacity) {
-        size_t newCapacity = expandedSize(requiredLength, base->preCapacity);
-        UChar* oldBuf = base->buf;
-        base->buf = reallocChars(base->buf, newCapacity);
-        if (!base->buf) {
-            base->buf = oldBuf;
-            return false;
-        }
-        base->capacity = newCapacity - base->preCapacity;
-    }
-    if (requiredLength > base->usedCapacity)
-        base->usedCapacity = requiredLength;
-
-    rep->checkConsistency();
-    return true;
-}
-
-bool UString::Rep::reserveCapacity(int capacity)
-{
-    // If this is an empty string there is no point 'growing' it - just allocate a new one.
-    // If the BaseString is shared with another string that is using more capacity than this
-    // string is, then growing the buffer won't help.
-    // If the BaseString's buffer is readonly, then it isn't allowed to grow.
-    UString::BaseString* base = baseString();
-    if (!base->buf || !base->capacity || (offset + len) != base->usedCapacity || base->isBufferReadOnly())
-        return false;
-    
-    // If there is already sufficient capacity, no need to grow!
-    if (capacity <= base->capacity)
-        return true;
-
-    checkConsistency();
-
-    size_t newCapacity = expandedSize(capacity, base->preCapacity);
-    UChar* oldBuf = base->buf;
-    base->buf = reallocChars(base->buf, newCapacity);
-    if (!base->buf) {
-        base->buf = oldBuf;
-        return false;
-    }
-    base->capacity = newCapacity - base->preCapacity;
-
-    checkConsistency();
-    return true;
-}
-
-void UString::expandCapacity(int requiredLength)
-{
-    if (!JSC::expandCapacity(m_rep.get(), requiredLength))
-        makeNull();
-}
-
-void UString::expandPreCapacity(int requiredPreCap)
-{
-    m_rep->checkConsistency();
-    ASSERT(!m_rep->baseString()->isBufferReadOnly());
-
-    BaseString* base = m_rep->baseString();
-
-    if (requiredPreCap > base->preCapacity) {
-        size_t newCapacity = expandedSize(requiredPreCap, base->capacity);
-        int delta = newCapacity - base->capacity - base->preCapacity;
-
-        UChar* newBuf = allocChars(newCapacity);
-        if (!newBuf) {
-            makeNull();
-            return;
-        }
-        copyChars(newBuf + delta, base->buf, base->capacity + base->preCapacity);
-        fastFree(base->buf);
-        base->buf = newBuf;
+    if (!c[0])
+        return &UString::Rep::empty();
 
 
-        base->preCapacity = newCapacity - base->capacity;
-    }
-    if (requiredPreCap > base->usedPreCapacity)
-        base->usedPreCapacity = requiredPreCap;
+    size_t length = strlen(c);
+    UChar* d;
+    PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, d);
+    if (!result)
+        return &UString::Rep::null();
 
 
-    m_rep->checkConsistency();
+    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 result;
 }
 
 }
 
-static PassRefPtr<UString::Rep> createRep(const char* c)
+static inline PassRefPtr<UString::Rep> createRep(const char* c, int length)
 {
     if (!c)
         return &UString::Rep::null();
 
 {
     if (!c)
         return &UString::Rep::null();
 
-    if (!c[0])
+    if (!length)
         return &UString::Rep::empty();
 
         return &UString::Rep::empty();
 
-    size_t length = strlen(c);
-    UChar* d = allocChars(length);
-    if (!d)
+    UChar* d;
+    PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, d);
+    if (!result)
         return &UString::Rep::null();
         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));
-    }
 
 
+    for (int i = 0; i < length; i++)
+        d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
+    return result;
 }
 
 UString::UString(const char* c)
 }
 
 UString::UString(const char* c)
@@ -582,240 +202,34 @@ UString::UString(const char* c)
 {
 }
 
 {
 }
 
-UString::UString(const UChar* c, int length)
+UString::UString(const char* c, int length)
+    : m_rep(createRep(c, length))
 {
 {
-    if (length == 0) 
-        m_rep = &Rep::empty();
-    else
-        m_rep = Rep::createCopying(c, length);
 }
 
 }
 
-UString::UString(UChar* c, int length, bool copy)
+UString::UString(const UChar* c, int length)
 {
 {
-    if (length == 0)
+    if (length == 0) 
         m_rep = &Rep::empty();
         m_rep = &Rep::empty();
-    else if (copy)
-        m_rep = Rep::createCopying(c, length);
     else
         m_rep = Rep::create(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 int newCapacityWithOverflowCheck(const int currentCapacity, const int extendLength, const bool plusOne = false)
-{
-    ASSERT_WITH_MESSAGE(extendLength >= 0, "extendedLength = %d", extendLength);
-
-    const int plusLength = plusOne ? 1 : 0;
-    if (currentCapacity > std::numeric_limits<int>::max() - extendLength - plusLength)
-        CRASH();
-
-    return currentCapacity + extendLength + plusLength;
-}
-
-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;
-    UString::BaseString* base = rep->baseString();
-
-    // possible cases:
-    if (tSize == 0) {
-        // t is empty
-    } else if (thisSize == 0) {
-        // this is empty
-        rep = UString::Rep::createCopying(tData, tSize);
-    } else if (rep == base && !base->isShared()) {
-        // this is direct and has refcount of 1 (so we can just alter it directly)
-        if (!expandCapacity(rep.get(), newCapacityWithOverflowCheck(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 == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) {
-        // this reaches the end of the buffer - extend it if it's long enough to append to
-        if (!expandCapacity(rep.get(), newCapacityWithOverflowCheck(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 in some way that prevents us from modifying base, so we must 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->baseString()->capacity = newCapacity;
-        }
-    }
-
-    rep->checkConsistency();
-
-    return rep.release();
-}
-
-static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Rep> r, const char* t)
+UString UString::createFromUTF8(const char* string)
 {
 {
-    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;
-    UString::BaseString* base = rep->baseString();
-
-    // 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 == base && !base->isShared()) {
-        // this is direct and has refcount of 1 (so we can just alter it directly)
-        expandCapacity(rep.get(), newCapacityWithOverflowCheck(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 == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) {
-        // this string reaches the end of the buffer - extend it
-        expandCapacity(rep.get(), newCapacityWithOverflowCheck(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 in some way that prevents us from modifying base, so we must 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->baseString()->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 bSize = b->size();
-    int aOffset = a->offset;
-
-    // possible cases:
-
-    UString::BaseString* aBase = a->baseString();
-    if (bSize == 1 && aOffset + aSize == aBase->usedCapacity && aOffset + aSize < aBase->capacity && !aBase->isBufferReadOnly()) {
-        // b is a single character (common fast case)
-        ++aBase->usedCapacity;
-        a->data()[aSize] = b->data()[0];
-        return UString::Rep::create(a, 0, aSize + 1);
-    }
-
-    // a is empty
-    if (aSize == 0)
-        return b;
-    // b is empty
-    if (bSize == 0)
-        return a;
-
-    int bOffset = b->offset;
-    int length = aSize + bSize;
-
-    UString::BaseString* bBase = b->baseString();
-    if (aOffset + aSize == aBase->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize
-        && (-bOffset != bBase->usedPreCapacity || aSize >= bSize) && !aBase->isBufferReadOnly()) {
-        // - 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(newCapacityWithOverflowCheck(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 == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize && !bBase->isBufferReadOnly()) {
-        // - 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->baseString()->capacity = newCapacity;
+    if (!string)
+        return null();
 
 
-    a->checkConsistency();
-    b->checkConsistency();
-    result->checkConsistency();
+    size_t length = strlen(string);
+    Vector<UChar, 1024> buffer(length);
+    UChar* p = buffer.data();
+    if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length))
+        return null();
 
 
-    return result;
+    return UString(buffer.data(), p - buffer.data());
 }
 
 }
 
-PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, int i)
+UString UString::from(int i)
 {
     UChar buf[1 + sizeof(i) * 3];
     UChar* end = buf + sizeof(buf) / sizeof(UChar);
 {
     UChar buf[1 + sizeof(i) * 3];
     UChar* end = buf + sizeof(buf) / sizeof(UChar);
@@ -826,7 +240,7 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, int i)
     else if (i == INT_MIN) {
         char minBuf[1 + sizeof(i) * 3];
         sprintf(minBuf, "%d", INT_MIN);
     else if (i == INT_MIN) {
         char minBuf[1 + sizeof(i) * 3];
         sprintf(minBuf, "%d", INT_MIN);
-        return concatenate(rep, minBuf);
+        return UString(minBuf);
     } else {
         bool negative = false;
         if (i < 0) {
     } else {
         bool negative = false;
         if (i < 0) {
@@ -841,89 +255,26 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, int i)
             *--p = '-';
     }
 
             *--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[80];
-    WTF::dtoa(result, 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';
-    }
-    
-    return concatenate(rep, buf);
+    return UString(p, static_cast<int>(end - p));
 }
 
 }
 
-UString UString::from(int i)
+UString UString::from(long long i)
 {
     UChar buf[1 + sizeof(i) * 3];
     UChar* end = buf + sizeof(buf) / sizeof(UChar);
     UChar* p = end;
 {
     UChar buf[1 + sizeof(i) * 3];
     UChar* end = buf + sizeof(buf) / sizeof(UChar);
     UChar* p = end;
-  
+
     if (i == 0)
         *--p = '0';
     if (i == 0)
         *--p = '0';
-    else if (i == INT_MIN) {
+    else if (i == std::numeric_limits<long long>::min()) {
         char minBuf[1 + sizeof(i) * 3];
         char minBuf[1 + sizeof(i) * 3];
-        snprintf(minBuf, 1 + sizeof(i) * 3, "%d", INT_MIN);
+#if OS(WINDOWS)
+        snprintf(minBuf, sizeof(minBuf) - 1, "%I64d", std::numeric_limits<long long>::min());
+#elif PLATFORM(IPHONE)
+        snprintf(minBuf, sizeof(minBuf), "%lld", std::numeric_limits<long long>::min());
+#else
+        snprintf(minBuf, sizeof(minBuf) - 1, "%lld", std::numeric_limits<long long>::min());
+#endif
         return UString(minBuf);
     } else {
         bool negative = false;
         return UString(minBuf);
     } else {
         bool negative = false;
@@ -991,69 +342,10 @@ UString UString::from(long l)
 
 UString UString::from(double d)
 {
 
 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[80];
-    WTF::dtoa(result, 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';
-        strlcpy(buf + i, result, sizeof(buf) - i);
-    } else if (decimalPoint <= 21 && decimalPoint > 0) {
-        if (length <= decimalPoint) {
-            strlcpy(buf + i, result, sizeof(buf) - i);
-            i += length;
-            for (int j = 0; j < decimalPoint - length; j++)
-                buf[i++] = '0';
-            buf[i] = '\0';
-        } else {
-            int len = (decimalPoint <= static_cast<int>(sizeof(buf)) - i ? decimalPoint : sizeof(buf) - i);
-            strncpy(buf + i, result, len);
-            i += len;
-            buf[i++] = '.';
-            strlcpy(buf + i, result + decimalPoint, sizeof(buf) - i);
-        }
-    } else if (result[0] < '0' || result[0] > '9')
-        strlcpy(buf + i, result, sizeof(buf) - i);
-    else {
-        buf[i++] = result[0];
-        if (length > 1) {
-            buf[i++] = '.';
-            strlcpy(buf + i, result + 1, sizeof(buf) - i);
-            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';
-        ASSERT(i <= static_cast<int>(sizeof(buf)));
-    }
-    
-    return UString(buf);
+    DtoaBuffer buffer;
+    unsigned length;
+    doubleToStringInJavaScriptFormat(d, buffer, &length);
+    return UString(buffer, length);
 }
 
 UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
 }
 
 UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
@@ -1078,24 +370,25 @@ UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, in
     if (totalLength == 0)
         return "";
 
     if (totalLength == 0)
         return "";
 
-    UChar* buffer = allocChars(totalLength);
-    if (!buffer)
+    UChar* buffer;
+    PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer);
+    if (!rep)
         return null();
 
     int maxCount = max(rangeCount, separatorCount);
     int bufferPos = 0;
     for (int i = 0; i < maxCount; i++) {
         if (i < rangeCount) {
         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);
+            UStringImpl::copyChars(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length);
             bufferPos += substringRanges[i].length;
         }
         if (i < separatorCount) {
             bufferPos += substringRanges[i].length;
         }
         if (i < separatorCount) {
-            copyChars(buffer + bufferPos, separators[i].data(), separators[i].size());
+            UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size());
             bufferPos += separators[i].size();
         }
     }
 
             bufferPos += separators[i].size();
         }
     }
 
-    return UString::Rep::create(buffer, totalLength);
+    return rep;
 }
 
 UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const
 }
 
 UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const
@@ -1107,149 +400,17 @@ UString UString::replaceRange(int rangeStart, int rangeLength, const UString& re
     if (totalLength == 0)
         return "";
 
     if (totalLength == 0)
         return "";
 
-    UChar* buffer = allocChars(totalLength);
-    if (!buffer)
+    UChar* buffer;
+    PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer);
+    if (!rep)
         return null();
 
         return null();
 
-    copyChars(buffer, data(), rangeStart);
-    copyChars(buffer + rangeStart, replacement.data(), replacementLength);
+    UStringImpl::copyChars(buffer, data(), rangeStart);
+    UStringImpl::copyChars(buffer + rangeStart, replacement.data(), replacementLength);
     int rangeEnd = rangeStart + rangeLength;
     int rangeEnd = rangeStart + rangeLength;
-    copyChars(buffer + rangeStart + replacementLength, data() + rangeEnd, size() - rangeEnd);
-
-    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;
-    BaseString* base = m_rep->baseString();
-
-    // possible cases:
-    if (thisSize == 0) {
-        // this is empty
-        *this = t;
-    } else if (tSize == 0) {
-        // t is empty
-    } else if (m_rep == base && !base->isShared()) {
-        // this is direct and has refcount of 1 (so we can just alter it directly)
-        expandCapacity(newCapacityWithOverflowCheck(thisOffset, length));
-        if (data()) {
-            copyChars(m_rep->data() + thisSize, t.data(), tSize);
-            m_rep->len = length;
-            m_rep->_hash = 0;
-        }
-    } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) {
-        // this reaches the end of the buffer - extend it if it's long enough to append to
-        expandCapacity(newCapacityWithOverflowCheck(thisOffset, length));
-        if (data()) {
-            copyChars(m_rep->data() + thisSize, t.data(), tSize);
-            m_rep = Rep::create(m_rep, 0, length);
-        }
-    } else {
-        // This is shared in some way that prevents us from modifying base, so we must 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->baseString()->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;
-}
+    UStringImpl::copyChars(buffer + rangeStart + replacementLength, data() + rangeEnd, size() - rangeEnd);
 
 
-UString& UString::appendNumeric(int i)
-{
-    m_rep = concatenate(rep(), i);
-    return *this;
-}
-
-UString& UString::appendNumeric(double d)
-{
-    m_rep = concatenate(rep(), d);
-    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();
-    BaseString* base = m_rep->baseString();
-
-    // 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->baseString()->capacity = newCapacity;
-        }
-    } else if (m_rep == base && !base->isShared()) {
-        // this is direct and has refcount of 1 (so we can just alter it directly)
-        expandCapacity(newCapacityWithOverflowCheck(thisOffset, length, true));
-        UChar* d = m_rep->data();
-        if (d) {
-            d[length] = c;
-            m_rep->len = length + 1;
-            m_rep->_hash = 0;
-        }
-    } else if (thisOffset + length == base->usedCapacity && length >= minShareSize && !base->isBufferReadOnly()) {
-        // this reaches the end of the string - extend it and share
-        expandCapacity(newCapacityWithOverflowCheck(thisOffset, length, true));
-        UChar* d = m_rep->data();
-        if (d) {
-            d[length] = c;
-            m_rep = Rep::create(m_rep, 0, length + 1);
-        }
-    } else {
-        // This is shared in some way that prevents us from modifying base, so we must 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->baseString()->capacity = newCapacity;
-        }
-    }
-
-    m_rep->checkConsistency();
-
-    return *this;
+    return rep;
 }
 
 bool UString::getCString(CStringBuffer& buffer) const
 }
 
 bool UString::getCString(CStringBuffer& buffer) const
@@ -1277,13 +438,15 @@ bool UString::getCString(CStringBuffer& buffer) const
 
 char* UString::ascii() const
 {
 
 char* UString::ascii() const
 {
+    static char* asciiBuffer = 0;
+
     int length = size();
     int neededSize = length + 1;
     int length = size();
     int neededSize = length + 1;
-    delete[] statBuffer;
-    statBuffer = new char[neededSize];
+    delete[] asciiBuffer;
+    asciiBuffer = new char[neededSize];
 
     const UChar* p = data();
 
     const UChar* p = data();
-    char* q = statBuffer;
+    char* q = asciiBuffer;
     const UChar* limit = p + length;
     while (p != limit) {
         *q = static_cast<char>(p[0]);
     const UChar* limit = p + length;
     while (p != limit) {
         *q = static_cast<char>(p[0]);
@@ -1292,7 +455,7 @@ char* UString::ascii() const
     }
     *q = '\0';
 
     }
     *q = '\0';
 
-    return statBuffer;
+    return asciiBuffer;
 }
 
 UString& UString::operator=(const char* c)
 }
 
 UString& UString::operator=(const char* c)
@@ -1308,22 +471,13 @@ UString& UString::operator=(const char* c)
     }
 
     int l = static_cast<int>(strlen(c));
     }
 
     int l = static_cast<int>(strlen(c));
-    UChar* d;
-    BaseString* base = m_rep->baseString();
-    if (!base->isShared() && l <= base->capacity && m_rep == base && m_rep->offset == 0 && base->preCapacity == 0) {
-        d = base->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
+    UChar* d = 0;
+    m_rep = Rep::tryCreateUninitialized(l, d);
+    if (m_rep) {
+        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
+    } else
+        makeNull();
 
     return *this;
 }
 
     return *this;
 }
@@ -1481,7 +635,7 @@ uint32_t UString::toStrictUInt32(bool* ok) const
         *ok = false;
 
     // Empty string is not OK.
         *ok = false;
 
     // Empty string is not OK.
-    int len = m_rep->len;
+    int len = m_rep->size();
     if (len == 0)
         return 0;
     const UChar* p = m_rep->data();
     if (len == 0)
         return 0;
     const UChar* p = m_rep->data();
@@ -1708,8 +862,8 @@ int compare(const UString& s1, const UString& s2)
 
 bool equal(const UString::Rep* r, const UString::Rep* b)
 {
 
 bool equal(const UString::Rep* r, const UString::Rep* b)
 {
-    int length = r->len;
-    if (length != b->len)
+    int length = r->size();
+    if (length != b->size())
         return false;
     const UChar* d = r->data();
     const UChar* s = b->data();
         return false;
     const UChar* d = r->data();
     const UChar* s = b->data();
index d01b75de7e3bdbce0bf023f405d636664fc647cf..0c13689a703b7cc978957684d44913e24a85bfa0 100644 (file)
@@ -24,6 +24,7 @@
 #define UString_h
 
 #include "Collector.h"
 #define UString_h
 
 #include "Collector.h"
+#include "UStringImpl.h"
 #include <stdint.h>
 #include <string.h>
 #include <wtf/Assertions.h>
 #include <stdint.h>
 #include <string.h>
 #include <wtf/Assertions.h>
@@ -40,8 +41,6 @@ namespace JSC {
     using WTF::PlacementNewAdoptType;
     using WTF::PlacementNewAdopt;
 
     using WTF::PlacementNewAdoptType;
     using WTF::PlacementNewAdopt;
 
-    class IdentifierTable;
-  
     class CString {
     public:
         CString()
     class CString {
     public:
         CString()
@@ -71,191 +70,49 @@ namespace JSC {
         char* m_data;
     };
 
         char* m_data;
     };
 
+    bool operator==(const CString&, const CString&);
+
     typedef Vector<char, 32> CStringBuffer;
 
     class UString {
         friend class JIT;
 
     public:
     typedef Vector<char, 32> CStringBuffer;
 
     class UString {
         friend class JIT;
 
     public:
-        typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar;
-        struct BaseString;
-        struct Rep : Noncopyable {
-            friend class JIT;
-
-            static PassRefPtr<Rep> create(UChar* buffer, int length)
-            {
-                return adoptRef(new BaseString(buffer, length));
-            }
-
-            static PassRefPtr<Rep> createEmptyBuffer(size_t size)
-            {
-                // Guard against integer overflow
-                if (size < (std::numeric_limits<size_t>::max() / sizeof(UChar))) {
-                    if (void * buf = tryFastMalloc(size * sizeof(UChar)))
-                        return adoptRef(new BaseString(static_cast<UChar*>(buf), 0, size));
-                }
-                return adoptRef(new BaseString(0, 0, 0));
-            }
-
-            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*);
-
-            // Uses SharedUChar to have joint ownership over the UChar*.
-            static PassRefPtr<Rep> create(UChar*, int, PassRefPtr<SharedUChar>);
-
-            SharedUChar* sharedBuffer();
-            void destroy();
-
-            bool baseIsSelf() const { return m_identifierTableAndFlags.isFlagSet(BaseStringFlag); }
-            UChar* data() const;
-            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 m_identifierTableAndFlags.get(); }
-            void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTableAndFlags.set(table); }
-
-            bool isStatic() const { return m_identifierTableAndFlags.isFlagSet(StaticFlag); }
-            void setStatic(bool);
-            void setBaseString(PassRefPtr<BaseString>);
-            BaseString* baseString();
-            const BaseString* baseString() const;
-
-            Rep* ref() { ++rc; return this; }
-            ALWAYS_INLINE void deref() { if (--rc == 0) destroy(); }
-
-            void checkConsistency() const;
-            enum UStringFlags {
-                StaticFlag,
-                BaseStringFlag
-            };
-
-            // 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;
-            PtrAndFlags<IdentifierTable, UStringFlags> m_identifierTableAndFlags;
-
-            static BaseString& null() { return *nullBaseString; }
-            static BaseString& empty() { return *emptyBaseString; }
-
-            bool reserveCapacity(int capacity);
-
-        protected:
-            // Constructor for use by BaseString subclass; they use the union with m_baseString for another purpose.
-            Rep(int length)
-                : offset(0)
-                , len(length)
-                , rc(1)
-                , _hash(0)
-                , m_baseString(0)
-            {
-            }
-
-            Rep(PassRefPtr<BaseString> base, int offsetInBase, int length)
-                : offset(offsetInBase)
-                , len(length)
-                , rc(1)
-                , _hash(0)
-                , m_baseString(base.releaseRef())
-            {
-                checkConsistency();
-            }
-
-            union {
-                // If !baseIsSelf()
-                BaseString* m_baseString;
-                // If baseIsSelf()
-                SharedUChar* m_sharedBuffer;
-            };
-
-        private:
-            // For SmallStringStorage which allocates an array and does initialization manually.
-            Rep() { }
-
-            friend class SmallStringsStorage;
-            friend void initializeUString();
-            JS_EXPORTDATA static BaseString* nullBaseString;
-            JS_EXPORTDATA static BaseString* emptyBaseString;
-        };
-
-
-        struct BaseString : public Rep {
-            bool isShared() { return rc != 1 || isBufferReadOnly(); }
-            void setSharedBuffer(PassRefPtr<SharedUChar>);
-
-            bool isBufferReadOnly()
-            {
-                if (!m_sharedBuffer)
-                    return false;
-                return slowIsBufferReadOnly();
-            }
-
-            // potentially shared data.
-            UChar* buf;
-            int preCapacity;
-            int usedPreCapacity;
-            int capacity;
-            int usedCapacity;
-
-            size_t reportedCost;
-
-        private:
-            BaseString(UChar* buffer, int length, int additionalCapacity = 0)
-                : Rep(length)
-                , buf(buffer)
-                , preCapacity(0)
-                , usedPreCapacity(0)
-                , capacity(length + additionalCapacity)
-                , usedCapacity(length)
-                , reportedCost(0)
-            {
-                m_identifierTableAndFlags.setFlag(BaseStringFlag);
-                checkConsistency();
-            }
-
-            SharedUChar* sharedBuffer();
-            bool slowIsBufferReadOnly();
-
-            friend struct Rep;
-            friend class SmallStringsStorage;
-            friend void initializeUString();
-        };
-
+        typedef UStringImpl Rep;
+    
     public:
     public:
+        // UString constructors passed char*s assume ISO Latin-1 encoding; for UTF8 use 'createFromUTF8', below.
         UString();
         UString();
-        UString(const char*);
+        UString(const char*); // Constructor for null-terminated string.
+        UString(const char*, int length);
         UString(const UChar*, int length);
         UString(const UChar*, int length);
-        UString(UChar*, int length, bool copy);
+        UString(const Vector<UChar>& buffer);
 
         UString(const UString& s)
             : m_rep(s.m_rep)
         {
         }
 
 
         UString(const UString& s)
             : m_rep(s.m_rep)
         {
         }
 
-        UString(const Vector<UChar>& buffer);
+        // Special constructor for cases where we overwrite an object in place.
+        UString(PlacementNewAdoptType)
+            : m_rep(PlacementNewAdopt)
+        {
+        }
 
         ~UString()
         {
         }
 
 
         ~UString()
         {
         }
 
-        // Special constructor for cases where we overwrite an object in place.
-        UString(PlacementNewAdoptType)
-            : m_rep(PlacementNewAdopt)
+        template<size_t inlineCapacity>
+        static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector)
         {
         {
+            return Rep::adopt(vector);
         }
 
         }
 
+        static UString createFromUTF8(const char*);
+
         static UString from(int);
         static UString from(int);
+        static UString from(long long);
         static UString from(unsigned int);
         static UString from(long);
         static UString from(double);
         static UString from(unsigned int);
         static UString from(long);
         static UString from(double);
@@ -280,14 +137,6 @@ namespace JSC {
 
         UString replaceRange(int rangeStart, int RangeEnd, const UString& replacement) const;
 
 
         UString replaceRange(int rangeStart, int RangeEnd, const UString& replacement) 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);
-        UString& appendNumeric(int);
-        UString& appendNumeric(double);
-
         bool getCString(CStringBuffer&) const;
 
         // NOTE: This method should only be used for *debugging* purposes as it
         bool getCString(CStringBuffer&) const;
 
         // NOTE: This method should only be used for *debugging* purposes as it
@@ -306,13 +155,10 @@ namespace JSC {
 
         UString& operator=(const char*c);
 
 
         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(); }
 
         const UChar* data() const { return m_rep->data(); }
 
-        bool isNull() const { return (m_rep == &Rep::null()); }
-        bool isEmpty() const { return (!m_rep->len); }
+        bool isNull() const { return m_rep == &Rep::null(); }
+        bool isEmpty() const { return !m_rep->size(); }
 
         bool is8Bit() const;
 
 
         bool is8Bit() const;
 
@@ -348,22 +194,9 @@ namespace JSC {
             ASSERT(m_rep);
         }
 
             ASSERT(m_rep);
         }
 
-        size_t cost() const;
-
-        // Attempt to grow this string such that it can grow to a total length of 'capacity'
-        // without reallocation.  This may fail a number of reasons - if the BasicString is
-        // shared and another string is using part of the capacity beyond our end point, if
-        // the realloc fails, or if this string is empty and has no storage.
-        //
-        // This method returns a boolean indicating success.
-        bool reserveCapacity(int capacity)
-        {
-            return m_rep->reserveCapacity(capacity);
-        }
+        size_t cost() const { return m_rep->cost(); }
 
     private:
 
     private:
-        void expandCapacity(int requiredLength);
-        void expandPreCapacity(int requiredPreCap);
         void makeNull();
 
         RefPtr<Rep> m_rep;
         void makeNull();
 
         RefPtr<Rep> m_rep;
@@ -371,13 +204,9 @@ namespace JSC {
 
         friend void initializeUString();
         friend bool operator==(const UString&, const UString&);
 
         friend void initializeUString();
         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);
 
 
-    inline bool operator==(const UString& s1, const UString& s2)
+    ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2)
     {
         int size = s1.size();
         switch (size) {
     {
         int size = s1.size();
         switch (size) {
@@ -423,117 +252,310 @@ namespace JSC {
         return !JSC::operator==(s1, s2);
     }
 
         return !JSC::operator==(s1, s2);
     }
 
-    bool operator==(const CString&, const CString&);
+    int compare(const UString&, const UString&);
 
 
-    inline UString operator+(const UString& s1, const UString& s2)
+    inline UString::UString()
+        : m_rep(&Rep::null())
     {
     {
-        RefPtr<UString::Rep> result = concatenate(s1.rep(), s2.rep());
-        return UString(result ? result.release() : UString::nullRep());
     }
 
     }
 
-    int compare(const UString&, const UString&);
+    // 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;
+    }
 
 
-    bool equal(const UString::Rep*, const UString::Rep*);
+    // 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::minExtraCost / sizeof(UChar);
 
 
-    inline PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<UString::Rep> rep, int offset, int length)
-    {
-        ASSERT(rep);
-        rep->checkConsistency();
+    struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > {
+        static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->existingHash(); }
+        static unsigned hash(JSC::UString::Rep* key) { return key->existingHash(); }
+    };
 
 
-        int repOffset = rep->offset;
+    void initializeUString();
 
 
-        PassRefPtr<BaseString> base = rep->baseString();
+    template<typename StringType>
+    class StringTypeAdapter {
+    };
 
 
-        ASSERT(-(offset + repOffset) <= base->usedPreCapacity);
-        ASSERT(offset + repOffset + length <= base->usedCapacity);
+    template<>
+    class StringTypeAdapter<char*> {
+    public:
+        StringTypeAdapter<char*>(char* buffer)
+            : m_buffer((unsigned char*)buffer)
+            , m_length(strlen(buffer))
+        {
+        }
 
 
-        // Steal the single reference this Rep was created with.
-        return adoptRef(new Rep(base, repOffset + offset, length));
-    }
+        unsigned length() { return m_length; }
 
 
-    inline UChar* UString::Rep::data() const
-    {
-        const BaseString* base = baseString();
-        return base->buf + base->preCapacity + offset;
-    }
+        void writeTo(UChar* destination)
+        {
+            for (unsigned i = 0; i < m_length; ++i)
+                destination[i] = m_buffer[i];
+        }
 
 
-    inline void UString::Rep::setStatic(bool v)
-    {
-        ASSERT(!identifierTable());
-        if (v)
-            m_identifierTableAndFlags.setFlag(StaticFlag);
-        else
-            m_identifierTableAndFlags.clearFlag(StaticFlag);
-    }
+    private:
+        const unsigned char* m_buffer;
+        unsigned m_length;
+    };
+
+    template<>
+    class StringTypeAdapter<const char*> {
+    public:
+        StringTypeAdapter<const char*>(const char* buffer)
+            : m_buffer((unsigned char*)buffer)
+            , m_length(strlen(buffer))
+        {
+        }
+
+        unsigned length() { return m_length; }
 
 
-    inline void UString::Rep::setBaseString(PassRefPtr<BaseString> base)
+        void writeTo(UChar* destination)
+        {
+            for (unsigned i = 0; i < m_length; ++i)
+                destination[i] = m_buffer[i];
+        }
+
+    private:
+        const unsigned char* m_buffer;
+        unsigned m_length;
+    };
+
+    template<>
+    class StringTypeAdapter<UString> {
+    public:
+        StringTypeAdapter<UString>(UString& string)
+            : m_data(string.data())
+            , m_length(string.size())
+        {
+        }
+
+        unsigned length() { return m_length; }
+
+        void writeTo(UChar* destination)
+        {
+            for (unsigned i = 0; i < m_length; ++i)
+                destination[i] = m_data[i];
+        }
+
+    private:
+        const UChar* m_data;
+        unsigned m_length;
+    };
+
+    template<typename StringType1, typename StringType2>
+    UString makeString(StringType1 string1, StringType2 string2)
     {
     {
-        ASSERT(base != this);
-        ASSERT(!baseIsSelf());
-        m_baseString = base.releaseRef();
+        StringTypeAdapter<StringType1> adapter1(string1);
+        StringTypeAdapter<StringType2> adapter2(string2);
+
+        UChar* buffer;
+        unsigned length = adapter1.length() + adapter2.length();
+        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
+        if (!resultImpl)
+            return UString();
+
+        UChar* result = buffer;
+        adapter1.writeTo(result);
+        result += adapter1.length();
+        adapter2.writeTo(result);
+
+        return resultImpl;
     }
 
     }
 
-    inline UString::BaseString* UString::Rep::baseString()
+    template<typename StringType1, typename StringType2, typename StringType3>
+    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3)
     {
     {
-        return !baseIsSelf() ? m_baseString : reinterpret_cast<BaseString*>(this) ;
+        StringTypeAdapter<StringType1> adapter1(string1);
+        StringTypeAdapter<StringType2> adapter2(string2);
+        StringTypeAdapter<StringType3> adapter3(string3);
+
+        UChar* buffer;
+        unsigned length = adapter1.length() + adapter2.length() + adapter3.length();
+        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
+        if (!resultImpl)
+            return UString();
+
+        UChar* result = buffer;
+        adapter1.writeTo(result);
+        result += adapter1.length();
+        adapter2.writeTo(result);
+        result += adapter2.length();
+        adapter3.writeTo(result);
+
+        return resultImpl;
     }
 
     }
 
-    inline const UString::BaseString* UString::Rep::baseString() const
+    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
+    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
     {
     {
-        return const_cast<Rep*>(this)->baseString();
+        StringTypeAdapter<StringType1> adapter1(string1);
+        StringTypeAdapter<StringType2> adapter2(string2);
+        StringTypeAdapter<StringType3> adapter3(string3);
+        StringTypeAdapter<StringType4> adapter4(string4);
+
+        UChar* buffer;
+        unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length();
+        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
+        if (!resultImpl)
+            return UString();
+
+        UChar* result = buffer;
+        adapter1.writeTo(result);
+        result += adapter1.length();
+        adapter2.writeTo(result);
+        result += adapter2.length();
+        adapter3.writeTo(result);
+        result += adapter3.length();
+        adapter4.writeTo(result);
+
+        return resultImpl;
     }
 
     }
 
-#ifdef NDEBUG
-    inline void UString::Rep::checkConsistency() const
+    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
+    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
     {
     {
+        StringTypeAdapter<StringType1> adapter1(string1);
+        StringTypeAdapter<StringType2> adapter2(string2);
+        StringTypeAdapter<StringType3> adapter3(string3);
+        StringTypeAdapter<StringType4> adapter4(string4);
+        StringTypeAdapter<StringType5> adapter5(string5);
+
+        UChar* buffer;
+        unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length();
+        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
+        if (!resultImpl)
+            return UString();
+
+        UChar* result = buffer;
+        adapter1.writeTo(result);
+        result += adapter1.length();
+        adapter2.writeTo(result);
+        result += adapter2.length();
+        adapter3.writeTo(result);
+        result += adapter3.length();
+        adapter4.writeTo(result);
+        result += adapter4.length();
+        adapter5.writeTo(result);
+
+        return resultImpl;
     }
     }
-#endif
 
 
-    inline UString::UString()
-        : m_rep(&Rep::null())
+    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
+    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
     {
     {
+        StringTypeAdapter<StringType1> adapter1(string1);
+        StringTypeAdapter<StringType2> adapter2(string2);
+        StringTypeAdapter<StringType3> adapter3(string3);
+        StringTypeAdapter<StringType4> adapter4(string4);
+        StringTypeAdapter<StringType5> adapter5(string5);
+        StringTypeAdapter<StringType6> adapter6(string6);
+
+        UChar* buffer;
+        unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length();
+        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
+        if (!resultImpl)
+            return UString();
+
+        UChar* result = buffer;
+        adapter1.writeTo(result);
+        result += adapter1.length();
+        adapter2.writeTo(result);
+        result += adapter2.length();
+        adapter3.writeTo(result);
+        result += adapter3.length();
+        adapter4.writeTo(result);
+        result += adapter4.length();
+        adapter5.writeTo(result);
+        result += adapter5.length();
+        adapter6.writeTo(result);
+
+        return resultImpl;
     }
 
     }
 
-    // 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
+    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
+    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
     {
     {
-        unsigned i = toStrictUInt32(ok);
-        if (ok && i >= 0xFFFFFFFFU)
-            *ok = false;
-        return i;
+        StringTypeAdapter<StringType1> adapter1(string1);
+        StringTypeAdapter<StringType2> adapter2(string2);
+        StringTypeAdapter<StringType3> adapter3(string3);
+        StringTypeAdapter<StringType4> adapter4(string4);
+        StringTypeAdapter<StringType5> adapter5(string5);
+        StringTypeAdapter<StringType6> adapter6(string6);
+        StringTypeAdapter<StringType7> adapter7(string7);
+
+        UChar* buffer;
+        unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length();
+        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
+        if (!resultImpl)
+            return UString();
+
+        UChar* result = buffer;
+        adapter1.writeTo(result);
+        result += adapter1.length();
+        adapter2.writeTo(result);
+        result += adapter2.length();
+        adapter3.writeTo(result);
+        result += adapter3.length();
+        adapter4.writeTo(result);
+        result += adapter4.length();
+        adapter5.writeTo(result);
+        result += adapter5.length();
+        adapter6.writeTo(result);
+        result += adapter6.length();
+        adapter7.writeTo(result);
+
+        return resultImpl;
     }
 
     }
 
-    // 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
+    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
+    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
     {
     {
-        BaseString* base = m_rep->baseString();
-        size_t capacity = (base->capacity + base->preCapacity) * sizeof(UChar);
-        size_t reportedCost = base->reportedCost;
-        ASSERT(capacity >= reportedCost);
-
-        size_t capacityDelta = capacity - reportedCost;
-
-        if (capacityDelta < static_cast<size_t>(minShareSize))
-            return 0;
-
-        base->reportedCost = capacity;
-
-        return capacityDelta;
+        StringTypeAdapter<StringType1> adapter1(string1);
+        StringTypeAdapter<StringType2> adapter2(string2);
+        StringTypeAdapter<StringType3> adapter3(string3);
+        StringTypeAdapter<StringType4> adapter4(string4);
+        StringTypeAdapter<StringType5> adapter5(string5);
+        StringTypeAdapter<StringType6> adapter6(string6);
+        StringTypeAdapter<StringType7> adapter7(string7);
+        StringTypeAdapter<StringType8> adapter8(string8);
+
+        UChar* buffer;
+        unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length() + adapter8.length();
+        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
+        if (!resultImpl)
+            return UString();
+
+        UChar* result = buffer;
+        adapter1.writeTo(result);
+        result += adapter1.length();
+        adapter2.writeTo(result);
+        result += adapter2.length();
+        adapter3.writeTo(result);
+        result += adapter3.length();
+        adapter4.writeTo(result);
+        result += adapter4.length();
+        adapter5.writeTo(result);
+        result += adapter5.length();
+        adapter6.writeTo(result);
+        result += adapter6.length();
+        adapter7.writeTo(result);
+        result += adapter7.length();
+        adapter8.writeTo(result);
+
+        return resultImpl;
     }
 
     }
 
-    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(); }
-    };
-
-    void initializeUString();
 } // namespace JSC
 
 namespace WTF {
 } // namespace JSC
 
 namespace WTF {
diff --git a/runtime/UStringImpl.cpp b/runtime/UStringImpl.cpp
new file mode 100644 (file)
index 0000000..4b0d1c9
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "UStringImpl.h"
+
+#include "Identifier.h"
+#include "UString.h"
+#include <wtf/unicode/UTF8.h>
+
+using namespace WTF::Unicode;
+using namespace std;
+
+namespace JSC {
+SharedUChar* UStringImpl::baseSharedBuffer()
+{
+    ASSERT((bufferOwnership() == BufferShared)
+        || ((bufferOwnership() == BufferOwned) && !m_dataBuffer.asPtr<void*>()));
+
+    if (bufferOwnership() != BufferShared)
+        m_dataBuffer = UntypedPtrAndBitfield(SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef(), BufferShared);
+
+    return m_dataBuffer.asPtr<SharedUChar*>();
+}
+
+SharedUChar* UStringImpl::sharedBuffer()
+{
+    if (m_length < s_minLengthToShare)
+        return 0;
+    ASSERT(!isStatic());
+
+    UStringImpl* owner = bufferOwnerString();
+    if (owner->bufferOwnership() == BufferInternal)
+        return 0;
+
+    return owner->baseSharedBuffer();
+}
+
+UStringImpl::~UStringImpl()
+{
+    ASSERT(!isStatic());
+    checkConsistency();
+
+    if (isIdentifier())
+        Identifier::remove(this);
+
+    if (bufferOwnership() != BufferInternal) {
+        if (bufferOwnership() == BufferOwned)
+            fastFree(m_data);
+        else if (bufferOwnership() == BufferSubstring)
+            m_dataBuffer.asPtr<UStringImpl*>()->deref();
+        else {
+            ASSERT(bufferOwnership() == BufferShared);
+            m_dataBuffer.asPtr<SharedUChar*>()->deref();
+        }
+    }
+}
+
+}
diff --git a/runtime/UStringImpl.h b/runtime/UStringImpl.h
new file mode 100644 (file)
index 0000000..abed637
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef UStringImpl_h
+#define UStringImpl_h
+
+#include <limits>
+#include <wtf/CrossThreadRefCounted.h>
+#include <wtf/OwnFastMallocPtr.h>
+#include <wtf/PossiblyNull.h>
+#include <wtf/StringHashFunctions.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC {
+
+class IdentifierTable;
+  
+typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar;
+
+class UntypedPtrAndBitfield {
+public:
+    UntypedPtrAndBitfield() {}
+
+    UntypedPtrAndBitfield(void* ptrValue, uintptr_t bitValue)
+        : m_value(reinterpret_cast<uintptr_t>(ptrValue) | bitValue)
+#ifndef NDEBUG
+        , m_leaksPtr(ptrValue)
+#endif
+    {
+        ASSERT(ptrValue == asPtr<void*>());
+        ASSERT((*this & ~s_alignmentMask) == bitValue);
+    }
+
+    template<typename T>
+    T asPtr() const { return reinterpret_cast<T>(m_value & s_alignmentMask); }
+
+    UntypedPtrAndBitfield& operator&=(uintptr_t bits)
+    {
+        m_value &= bits | s_alignmentMask;
+        return *this;
+    }
+
+    UntypedPtrAndBitfield& operator|=(uintptr_t bits)
+    {
+        m_value |= bits & ~s_alignmentMask;
+        return *this;
+    }
+
+    uintptr_t operator&(uintptr_t mask) const
+    {
+        return m_value & mask & ~s_alignmentMask;
+    }
+
+private:
+    static const uintptr_t s_alignmentMask = ~static_cast<uintptr_t>(0x7);
+    uintptr_t m_value;
+#ifndef NDEBUG
+        void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced.
+#endif
+};
+
+class UStringImpl : Noncopyable {
+public:
+    template<size_t inlineCapacity>
+    static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector)
+    {
+        if (unsigned length = vector.size())
+            return adoptRef(new UStringImpl(vector.releaseBuffer(), length, BufferOwned));
+        return &empty();
+    }
+
+    static PassRefPtr<UStringImpl> create(const UChar* buffer, int length)
+    {
+        UChar* newBuffer;
+        if (PassRefPtr<UStringImpl> impl = tryCreateUninitialized(length, newBuffer)) {
+            copyChars(newBuffer, buffer, length);
+            return impl;
+        }
+        return &null();
+    }
+
+    static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, int offset, int length)
+    {
+        ASSERT(rep);
+        rep->checkConsistency();
+        return adoptRef(new UStringImpl(rep->m_data + offset, length, rep->bufferOwnerString()));
+    }
+
+    static PassRefPtr<UStringImpl> create(PassRefPtr<SharedUChar> sharedBuffer, UChar* buffer, int length)
+    {
+        return adoptRef(new UStringImpl(buffer, length, sharedBuffer));
+    }
+
+    static PassRefPtr<UStringImpl> createUninitialized(unsigned length, UChar*& output)
+    {
+        if (!length) {
+            output = 0;
+            return &empty();
+        }
+
+        if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar)))
+            CRASH();
+        UStringImpl* resultImpl = static_cast<UStringImpl*>(fastMalloc(sizeof(UChar) * length + sizeof(UStringImpl)));
+        output = reinterpret_cast<UChar*>(resultImpl + 1);
+        return adoptRef(new(resultImpl) UStringImpl(output, length, BufferInternal));
+    }
+
+    static PassRefPtr<UStringImpl> tryCreateUninitialized(unsigned length, UChar*& output)
+    {
+        if (!length) {
+            output = 0;
+            return &empty();
+        }
+
+        if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar)))
+            return 0;
+        UStringImpl* resultImpl;
+        if (!tryFastMalloc(sizeof(UChar) * length + sizeof(UStringImpl)).getValue(resultImpl))
+            return 0;
+        output = reinterpret_cast<UChar*>(resultImpl + 1);
+        return adoptRef(new(resultImpl) UStringImpl(output, length, BufferInternal));
+    }
+
+    SharedUChar* sharedBuffer();
+    UChar* data() const { return m_data; }
+    int size() const { return m_length; }
+    size_t cost()
+    {
+        // For substrings, return the cost of the base string.
+        if (bufferOwnership() == BufferSubstring)
+            return m_dataBuffer.asPtr<UStringImpl*>()->cost();
+
+        if (m_dataBuffer & s_reportedCostBit)
+            return 0;
+        m_dataBuffer |= s_reportedCostBit;
+        return m_length;
+    }
+    unsigned hash() const { if (!m_hash) m_hash = computeHash(data(), m_length); return m_hash; }
+    unsigned existingHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers
+    void setHash(unsigned hash) { ASSERT(hash == computeHash(data(), m_length)); m_hash = hash; } // fast path for Identifiers
+    bool isIdentifier() const { return m_isIdentifier; }
+    void setIsIdentifier(bool isIdentifier) { m_isIdentifier = isIdentifier; }
+
+    UStringImpl* ref() { m_refCount += s_refCountIncrement; return this; }
+    ALWAYS_INLINE void deref() { if (!(m_refCount -= s_refCountIncrement)) delete this; }
+
+    static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters)
+    {
+        if (numCharacters <= s_copyCharsInlineCutOff) {
+            for (unsigned i = 0; i < numCharacters; ++i)
+                destination[i] = source[i];
+        } else
+            memcpy(destination, source, numCharacters * sizeof(UChar));
+    }
+
+    static unsigned computeHash(const UChar* s, int length) { ASSERT(length >= 0); return WTF::stringHash(s, length); }
+    static unsigned computeHash(const char* s, int length) { ASSERT(length >= 0); return WTF::stringHash(s, length); }
+    static unsigned computeHash(const char* s) { return WTF::stringHash(s); }
+
+    static UStringImpl& null() { return *s_null; }
+    static UStringImpl& empty() { return *s_empty; }
+
+    ALWAYS_INLINE void checkConsistency() const
+    {
+        // There is no recursion of substrings.
+        ASSERT(bufferOwnerString()->bufferOwnership() != BufferSubstring);
+        // Static strings cannot be put in identifier tables, because they are globally shared.
+        ASSERT(!isStatic() || !isIdentifier());
+    }
+
+private:
+    enum BufferOwnership {
+        BufferInternal,
+        BufferOwned,
+        BufferSubstring,
+        BufferShared,
+    };
+
+    // For SmallStringStorage, which allocates an array and uses an in-place new.
+    UStringImpl() { }
+
+    // Used to construct normal strings with an internal or external buffer.
+    UStringImpl(UChar* data, int length, BufferOwnership ownership)
+        : m_data(data)
+        , m_length(length)
+        , m_refCount(s_refCountIncrement)
+        , m_hash(0)
+        , m_isIdentifier(false)
+        , m_dataBuffer(0, ownership)
+    {
+        ASSERT((ownership == BufferInternal) || (ownership == BufferOwned));
+        checkConsistency();
+    }
+
+    // Used to construct static strings, which have an special refCount that can never hit zero.
+    // This means that the static string will never be destroyed, which is important because
+    // static strings will be shared across threads & ref-counted in a non-threadsafe manner.
+    enum StaticStringConstructType { ConstructStaticString };
+    UStringImpl(UChar* data, int length, StaticStringConstructType)
+        : m_data(data)
+        , m_length(length)
+        , m_refCount(s_staticRefCountInitialValue)
+        , m_hash(0)
+        , m_isIdentifier(false)
+        , m_dataBuffer(0, BufferOwned)
+    {
+        checkConsistency();
+    }
+
+    // Used to create new strings that are a substring of an existing string.
+    UStringImpl(UChar* data, int length, PassRefPtr<UStringImpl> base)
+        : m_data(data)
+        , m_length(length)
+        , m_refCount(s_refCountIncrement)
+        , m_hash(0)
+        , m_isIdentifier(false)
+        , m_dataBuffer(base.releaseRef(), BufferSubstring)
+    {
+        // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes
+        // that all pointers will be at least 8-byte aligned, we cannot guarantee that of
+        // UStringImpls that are not heap allocated.
+        ASSERT(m_dataBuffer.asPtr<UStringImpl*>()->size());
+        ASSERT(!m_dataBuffer.asPtr<UStringImpl*>()->isStatic());
+        checkConsistency();
+    }
+
+    // Used to construct new strings sharing an existing shared buffer.
+    UStringImpl(UChar* data, int length, PassRefPtr<SharedUChar> sharedBuffer)
+        : m_data(data)
+        , m_length(length)
+        , m_refCount(s_refCountIncrement)
+        , m_hash(0)
+        , m_isIdentifier(false)
+        , m_dataBuffer(sharedBuffer.releaseRef(), BufferShared)
+    {
+        checkConsistency();
+    }
+
+    using Noncopyable::operator new;
+    void* operator new(size_t, void* inPlace) { return inPlace; }
+
+    ~UStringImpl();
+
+    // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings.
+    static const int s_minLengthToShare = 10;
+    static const unsigned s_copyCharsInlineCutOff = 20;
+    static const uintptr_t s_bufferOwnershipMask = 3;
+    static const uintptr_t s_reportedCostBit = 4;
+    // We initialize and increment/decrement the refCount for all normal (non-static) strings by the value 2.
+    // We initialize static strings with an odd number (specifically, 1), such that the refCount cannot reach zero.
+    static const int s_refCountIncrement = 2;
+    static const int s_staticRefCountInitialValue = 1;
+
+    UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() :  this; }
+    const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() :  this; }
+    SharedUChar* baseSharedBuffer();
+    unsigned bufferOwnership() const { return m_dataBuffer & s_bufferOwnershipMask; }
+    bool isStatic() const { return m_refCount & 1; }
+
+    // unshared data
+    UChar* m_data;
+    int m_length;
+    unsigned m_refCount;
+    mutable unsigned m_hash : 31;
+    mutable unsigned m_isIdentifier : 1;
+    UntypedPtrAndBitfield m_dataBuffer;
+
+    JS_EXPORTDATA static UStringImpl* s_null;
+    JS_EXPORTDATA static UStringImpl* s_empty;
+
+    friend class JIT;
+    friend class SmallStringsStorage;
+    friend void initializeUString();
+};
+
+bool equal(const UStringImpl*, const UStringImpl*);
+
+}
+
+#endif
diff --git a/runtime/WeakGCMap.h b/runtime/WeakGCMap.h
new file mode 100644 (file)
index 0000000..39a91c5
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WeakGCMap_h
+#define WeakGCMap_h
+
+#include "Collector.h"
+#include <wtf/HashMap.h>
+
+namespace JSC {
+
+class JSCell;
+
+// A HashMap whose get() function returns emptyValue() for cells awaiting destruction.
+template<typename KeyType, typename MappedType>
+class WeakGCMap : public FastAllocBase {
+    /*
+    Invariants:
+        * A value enters the WeakGCMap marked. (Guaranteed by set().)
+        * A value that becomes unmarked leaves the WeakGCMap before being recycled. (Guaranteed by the value's destructor removing it from the WeakGCMap.)
+        * A value that becomes unmarked leaves the WeakGCMap before becoming marked again. (Guaranteed by all destructors running before the mark phase begins.)
+        * During the mark phase, all values in the WeakGCMap are valid. (Guaranteed by all destructors running before the mark phase begins.)
+    */
+
+public:
+    typedef typename HashMap<KeyType, MappedType>::iterator iterator;
+    typedef typename HashMap<KeyType, MappedType>::const_iterator const_iterator;
+    
+    bool isEmpty() { return m_map.isEmpty(); }
+
+    MappedType get(const KeyType& key) const;
+    pair<iterator, bool> set(const KeyType&, const MappedType&); 
+    MappedType take(const KeyType& key);
+
+    // These unchecked functions provide access to a value even if the value's
+    // mark bit is not set. This is used, among other things, to retrieve values
+    // during the GC mark phase, which begins by clearing all mark bits.
+
+    MappedType uncheckedGet(const KeyType& key) const { return m_map.get(key); }
+    bool uncheckedRemove(const KeyType&, const MappedType&);
+
+    iterator uncheckedBegin() { return m_map.begin(); }
+    iterator uncheckedEnd() { return m_map.end(); }
+
+    const_iterator uncheckedBegin() const { return m_map.begin(); }
+    const_iterator uncheckedEnd() const { return m_map.end(); }
+
+private:
+    HashMap<KeyType, MappedType> m_map;
+};
+
+template<typename KeyType, typename MappedType>
+inline MappedType WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const
+{
+    MappedType result = m_map.get(key);
+    if (result == HashTraits<MappedType>::emptyValue())
+        return result;
+    if (!Heap::isCellMarked(result))
+        return HashTraits<MappedType>::emptyValue();
+    return result;
+}
+
+template<typename KeyType, typename MappedType>
+MappedType WeakGCMap<KeyType, MappedType>::take(const KeyType& key)
+{
+    MappedType result = m_map.take(key);
+    if (result == HashTraits<MappedType>::emptyValue())
+        return result;
+    if (!Heap::isCellMarked(result))
+        return HashTraits<MappedType>::emptyValue();
+    return result;
+}
+
+template<typename KeyType, typename MappedType>
+pair<typename HashMap<KeyType, MappedType>::iterator, bool> WeakGCMap<KeyType, MappedType>::set(const KeyType& key, const MappedType& value)
+{
+    Heap::markCell(value); // If value is newly allocated, it's not marked, so mark it now.
+    pair<iterator, bool> result = m_map.add(key, value);
+    if (!result.second) { // pre-existing entry
+        result.second = !Heap::isCellMarked(result.first->second);
+        result.first->second = value;
+    }
+    return result;
+}
+
+template<typename KeyType, typename MappedType>
+bool WeakGCMap<KeyType, MappedType>::uncheckedRemove(const KeyType& key, const MappedType& value)
+{
+    iterator it = m_map.find(key);
+    if (it == m_map.end())
+        return false;
+    if (it->second != value)
+        return false;
+    m_map.remove(it);
+    return true;
+}
+
+} // namespace JSC
+
+#endif // WeakGCMap_h
diff --git a/runtime/WeakGCPtr.h b/runtime/WeakGCPtr.h
new file mode 100644 (file)
index 0000000..3ed4645
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WeakGCPtr_h
+#define WeakGCPtr_h
+
+#include "Collector.h"
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+// A smart pointer whose get() function returns 0 for cells awaiting destruction.
+template <typename T> class WeakGCPtr : Noncopyable {
+public:
+    WeakGCPtr() : m_ptr(0) { }
+    WeakGCPtr(T* ptr) { assign(ptr); }
+
+    T* get() const
+    {
+        if (!m_ptr || !Heap::isCellMarked(m_ptr))
+            return 0;
+        return m_ptr;
+    }
+    
+    void clear(JSCell* ptr)
+    {
+        if (ptr == m_ptr)
+            m_ptr = 0;
+    }
+
+    T& operator*() const { return *get(); }
+    T* operator->() const { return get(); }
+    
+    bool operator!() const { return !get(); }
+
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
+#if COMPILER(WINSCW)
+    operator bool() const { return m_ptr; }
+#else
+    typedef T* WeakGCPtr::*UnspecifiedBoolType;
+    operator UnspecifiedBoolType() const { return get() ? &WeakGCPtr::m_ptr : 0; }
+#endif
+
+    WeakGCPtr& operator=(T*);
+
+private:
+    void assign(T* ptr)
+    {
+        if (ptr)
+            Heap::markCell(ptr);
+        m_ptr = ptr;
+    }
+
+    T* m_ptr;
+};
+
+template <typename T> inline WeakGCPtr<T>& WeakGCPtr<T>::operator=(T* optr)
+{
+    assign(optr);
+    return *this;
+}
+
+template <typename T, typename U> inline bool operator==(const WeakGCPtr<T>& a, const WeakGCPtr<U>& b)
+{ 
+    return a.get() == b.get(); 
+}
+
+template <typename T, typename U> inline bool operator==(const WeakGCPtr<T>& a, U* b)
+{ 
+    return a.get() == b; 
+}
+
+template <typename T, typename U> inline bool operator==(T* a, const WeakGCPtr<U>& b) 
+{
+    return a == b.get(); 
+}
+
+template <typename T, typename U> inline bool operator!=(const WeakGCPtr<T>& a, const WeakGCPtr<U>& b)
+{ 
+    return a.get() != b.get(); 
+}
+
+template <typename T, typename U> inline bool operator!=(const WeakGCPtr<T>& a, U* b)
+{
+    return a.get() != b; 
+}
+
+template <typename T, typename U> inline bool operator!=(T* a, const WeakGCPtr<U>& b)
+{ 
+    return a != b.get(); 
+}
+
+template <typename T, typename U> inline WeakGCPtr<T> static_pointer_cast(const WeakGCPtr<U>& p)
+{ 
+    return WeakGCPtr<T>(static_cast<T*>(p.get())); 
+}
+
+template <typename T, typename U> inline WeakGCPtr<T> const_pointer_cast(const WeakGCPtr<U>& p)
+{ 
+    return WeakGCPtr<T>(const_cast<T*>(p.get())); 
+}
+
+template <typename T> inline T* getPtr(const WeakGCPtr<T>& p)
+{
+    return p.get();
+}
+
+} // namespace JSC
+
+#endif // WeakGCPtr_h
diff --git a/runtime/WeakRandom.h b/runtime/WeakRandom.h
new file mode 100644 (file)
index 0000000..ff3995e
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ *
+ * Copyright (c) 2009 Ian C. Bullard
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WeakRandom_h
+#define WeakRandom_h
+
+#include <limits.h>
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+class WeakRandom {
+public:
+    WeakRandom(unsigned seed)
+        : m_low(seed ^ 0x49616E42)
+        , m_high(seed)
+    {
+    }
+
+    double get()
+    {
+        return advance() / (UINT_MAX + 1.0);
+    }
+
+private:
+    unsigned advance()
+    {
+        m_high = (m_high << 16) + (m_high >> 16);
+        m_high += m_low;
+        m_low += m_high;
+        return m_high;
+    }
+
+    unsigned m_low;
+    unsigned m_high;
+};
+
+} // namespace JSC
+
+#endif // WeakRandom_h
index f8877250cd8a57e331d8a9514830c08a719ba306..f13e9d767936aa68413571baea9dace053fbc231 100644 (file)
 
     var DST_END_1998 = UTC( GetFirstSundayInNovember(TimeFromYear(1998)) + 2*msPerHour );
 
 
     var DST_END_1998 = UTC( GetFirstSundayInNovember(TimeFromYear(1998)) + 2*msPerHour );
 
-    addTestCase( now );
 /*
 /*
+    // We don't use |now| because it fails every night at midnight.
+    // The test is more reproducable if we use concrete times.
+    addTestCase( now );
     addTestCase( TIME_YEAR_0 );
     addTestCase( TIME_1970 );
     addTestCase( TIME_1900 );
     addTestCase( TIME_2000 );
     addTestCase( UTC_FEB_29_2000 );
     addTestCase( TIME_YEAR_0 );
     addTestCase( TIME_1970 );
     addTestCase( TIME_1900 );
     addTestCase( TIME_2000 );
     addTestCase( UTC_FEB_29_2000 );
+*/
     addTestCase( UTC_JAN_1_2005 );
     addTestCase( UTC_JAN_1_2005 );
+/*
     addTestCase( DST_START_1998 );
     addTestCase( DST_START_1998-1 );
     addTestCase( DST_START_1998+1 );
     addTestCase( DST_START_1998 );
     addTestCase( DST_START_1998-1 );
     addTestCase( DST_START_1998+1 );
index 437a8093228f3c002f8064eea045543c6ff36831..8dcf1a4e55e748af89ef59f6c240618dcc233277 100644 (file)
     var UTC_JAN_1_2005 = TIME_2000 + TimeInYear(2000)+TimeInYear(2001)+
     TimeInYear(2002)+TimeInYear(2003)+TimeInYear(2004);
 
     var UTC_JAN_1_2005 = TIME_2000 + TimeInYear(2000)+TimeInYear(2001)+
     TimeInYear(2002)+TimeInYear(2003)+TimeInYear(2004);
 
-    addTestCase( now );
 /*
 /*
+    // We don't use |now| because it fails every night at midnight.
+    // The test is more reproducable if we use concrete times.
+    addTestCase( now );
+
     addTestCase( TIME_YEAR_0 );
     addTestCase( TIME_1970 );
     addTestCase( TIME_1900 );
     addTestCase( TIME_2000 );
     addTestCase( UTC_FEB_29_2000 );
     addTestCase( TIME_YEAR_0 );
     addTestCase( TIME_1970 );
     addTestCase( TIME_1900 );
     addTestCase( TIME_2000 );
     addTestCase( UTC_FEB_29_2000 );
+*/
     addTestCase( UTC_JAN_1_2005 );
     addTestCase( UTC_JAN_1_2005 );
+/*
 
     testcases[tc++] = new TestCase( SECTION,
                                     "(new Date(NaN)).getDay()",
 
     testcases[tc++] = new TestCase( SECTION,
                                     "(new Date(NaN)).getDay()",
index 16f265c352be90f252f86160e3c03c2e5f456d5a..3eb51cbcdfdfa77ceff6d2ac2454a678c2063b63 100644 (file)
@@ -56,8 +56,15 @@ function AddRegExpCases( re, s, g, i, m, l ) {
                  s,
                  re.source );
 
                  s,
                  re.source );
 
+/*
+ * http://bugzilla.mozilla.org/show_bug.cgi?id=225550 changed
+ * the behavior of toString() and toSource() on empty regexps.
+ * So branch if |s| is the empty string -
+ */
+    var S = s? s : '(?:)';
+
     AddTestCase( re + ".toString()",
     AddTestCase( re + ".toString()",
-                 "/" + s +"/" + (g?"g":"") + (i?"i":"") +(m?"m":""),
+                 "/" + S +"/" + (g?"g":"") + (i?"i":"") +(m?"m":""),
                  re.toString() );
 
     AddTestCase( re + ".global",
                  re.toString() );
 
     AddTestCase( re + ".global",
index 554b934efb5551983996bba232c60215645511a9..b08b772811596e74dc5dd6a19aee38697e7f58d7 100644 (file)
@@ -41,7 +41,7 @@
     // var re = new RegExp(); re.toString()
        var re = new RegExp();
        testcases[count++] = new TestCase ( SECTION, "var re = new RegExp(); re.toString()",
     // var re = new RegExp(); re.toString()
        var re = new RegExp();
        testcases[count++] = new TestCase ( SECTION, "var re = new RegExp(); re.toString()",
-                                           '//', re.toString());
+                                           '/(?:)/', re.toString());
 
     // re = /.+/; re.toString();
     re = /.+/;
 
     // re = /.+/; re.toString();
     re = /.+/;
index 483dce002fe70e4063f174e39d170afc4b631051..13324e72b9bfe744fa3925b977aa774cbe71b8d6 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <wtf/unicode/Unicode.h>
 
 
 #include <wtf/unicode/Unicode.h>
 
-#if COMPILER(GCC) && PLATFORM(X86)
+#if COMPILER(GCC) && CPU(X86)
 #define WREC_CALL __attribute__ ((regparm (3)))
 #else
 #define WREC_CALL
 #define WREC_CALL __attribute__ ((regparm (3)))
 #else
 #define WREC_CALL
index e2e8abaf05ec128cc5806c97d2020e2b0b9740fb..7105984519dbeccac8fb0a4ad61c168a9bd54410 100644 (file)
@@ -40,10 +40,10 @@ namespace JSC { namespace WREC {
 
 void Generator::generateEnter()
 {
 
 void Generator::generateEnter()
 {
-#if PLATFORM(X86)
+#if CPU(X86)
     // On x86 edi & esi are callee preserved registers.
     // On x86 edi & esi are callee preserved registers.
-    push(X86::edi);
-    push(X86::esi);
+    push(X86Registers::edi);
+    push(X86Registers::esi);
     
 #if COMPILER(MSVC)
     // Move the arguments into registers.
     
 #if COMPILER(MSVC)
     // Move the arguments into registers.
@@ -71,9 +71,9 @@ void Generator::generateReturnSuccess()
     store32(index, Address(output, 4)); // match end
     
     // Restore callee save registers.
     store32(index, Address(output, 4)); // match end
     
     // Restore callee save registers.
-#if PLATFORM(X86)
-    pop(X86::esi);
-    pop(X86::edi);
+#if CPU(X86)
+    pop(X86Registers::esi);
+    pop(X86Registers::edi);
 #endif
     ret();
 }
 #endif
     ret();
 }
@@ -110,9 +110,9 @@ void Generator::generateReturnFailure()
     pop();
     move(Imm32(-1), returnRegister);
 
     pop();
     move(Imm32(-1), returnRegister);
 
-#if PLATFORM(X86)
-    pop(X86::esi);
-    pop(X86::edi);
+#if CPU(X86)
+    pop(X86Registers::esi);
+    pop(X86Registers::edi);
 #endif
     ret();
 }
 #endif
     ret();
 }
index 8562cac9b3710fd1b8724999b392cd44374dd918..d707a6e64c39b4eaedae3c1a2ccc024ef6774ccf 100644 (file)
@@ -62,27 +62,27 @@ namespace JSC {
         {
         }
 
         {
         }
 
-#if PLATFORM(X86)
-        static const RegisterID input = X86::eax;
-        static const RegisterID index = X86::edx;
-        static const RegisterID length = X86::ecx;
-        static const RegisterID output = X86::edi;
+#if CPU(X86)
+        static const RegisterID input = X86Registers::eax;
+        static const RegisterID index = X86Registers::edx;
+        static const RegisterID length = X86Registers::ecx;
+        static const RegisterID output = X86Registers::edi;
 
 
-        static const RegisterID character = X86::esi;
-        static const RegisterID repeatCount = X86::ebx; // How many times the current atom repeats in the current match.
+        static const RegisterID character = X86Registers::esi;
+        static const RegisterID repeatCount = X86Registers::ebx; // How many times the current atom repeats in the current match.
 
 
-        static const RegisterID returnRegister = X86::eax;
+        static const RegisterID returnRegister = X86Registers::eax;
 #endif
 #endif
-#if PLATFORM(X86_64)
-        static const RegisterID input = X86::edi;
-        static const RegisterID index = X86::esi;
-        static const RegisterID length = X86::edx;
-        static const RegisterID output = X86::ecx;
+#if CPU(X86_64)
+        static const RegisterID input = X86Registers::edi;
+        static const RegisterID index = X86Registers::esi;
+        static const RegisterID length = X86Registers::edx;
+        static const RegisterID output = X86Registers::ecx;
 
 
-        static const RegisterID character = X86::eax;
-        static const RegisterID repeatCount = X86::ebx; // How many times the current atom repeats in the current match.
+        static const RegisterID character = X86Registers::eax;
+        static const RegisterID repeatCount = X86Registers::ebx; // How many times the current atom repeats in the current match.
 
 
-        static const RegisterID returnRegister = X86::eax;
+        static const RegisterID returnRegister = X86Registers::eax;
 #endif
 
         void generateEnter();
 #endif
 
         void generateEnter();
diff --git a/wscript b/wscript
new file mode 100644 (file)
index 0000000..f5a041f
--- /dev/null
+++ b/wscript
@@ -0,0 +1,104 @@
+#! /usr/bin/env python
+
+# Copyright (C) 2009 Kevin Ollivier  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this 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. 
+#
+# JavaScriptCore build script for the waf build system
+
+import commands
+
+from settings import *
+
+jscore_excludes = ['jsc.cpp', 'ucptable.cpp']
+jscore_excludes.extend(get_excludes(jscore_dir, ['*CF.cpp', '*Symbian.cpp']))
+
+sources = []
+
+jscore_excludes.extend(get_excludes(jscore_dir, ['*None.cpp']))
+
+if building_on_win32:
+    jscore_excludes += ['ExecutableAllocatorPosix.cpp', 'MarkStackPosix.cpp', 'ThreadingPthreads.cpp']
+    sources += ['jit/ExecutableAllocatorWin.cpp', 'runtime/MarkStackWin.cpp']
+else:
+    jscore_excludes.append('JSStringRefBSTR.cpp')
+    jscore_excludes.extend(get_excludes(jscore_dir, ['*Win.cpp']))
+
+def generate_jscore_derived_sources():
+    # build the derived sources
+    js_dir = jscore_dir
+    if building_on_win32:
+        js_dir = get_output('cygpath --unix "%s"' % js_dir)
+    derived_sources_dir = os.path.join(jscore_dir, 'DerivedSources')
+    if not os.path.exists(derived_sources_dir):
+        os.mkdir(derived_sources_dir)
+
+    olddir = os.getcwd()
+    os.chdir(derived_sources_dir)
+
+    command = 'make -f %s/DerivedSources.make JavaScriptCore=%s BUILT_PRODUCTS_DIR=%s all FEATURE_DEFINES="%s"' % (js_dir, js_dir, js_dir, ' '.join(feature_defines))
+    os.system(command)
+    os.chdir(olddir)
+
+def set_options(opt):
+    common_set_options(opt)
+
+def configure(conf):
+    common_configure(conf)
+    generate_jscore_derived_sources()
+    
+def build(bld):
+    import Options
+
+    full_dirs = get_dirs_for_features(jscore_dir, features=[build_port], dirs=jscore_dirs)
+
+    includes = common_includes + full_dirs
+
+    # 1. A simple program
+    jscore = bld.new_task_gen(
+        features = 'cxx cstaticlib',
+        includes = '. .. assembler wrec DerivedSources ForwardingHeaders ' + ' '.join(includes),
+        source = sources,
+        target = 'jscore',
+        uselib = 'WX ICU ' + get_config(),
+        uselib_local = '',
+        install_path = output_dir)
+
+    jscore.find_sources_in_dirs(full_dirs, excludes = jscore_excludes)  
+        
+    obj = bld.new_task_gen(
+        features = 'cxx cprogram',
+        includes = '. .. assembler wrec DerivedSources ForwardingHeaders ' + ' '.join(includes),
+        source = 'jsc.cpp',
+        target = 'jsc',
+        uselib = 'WX ICU ' + get_config(),
+        uselib_local = 'jscore',
+        install_path = output_dir,
+        )
+        
+    # we'll get an error if exceptions are on because of an unwind error when using __try
+    if building_on_win32:
+        flags = obj.env.CXXFLAGS
+        flags.remove('/EHsc')
+        obj.env.CXXFLAGS = flags
+
+    bld.install_files(os.path.join(output_dir, 'JavaScriptCore'), 'API/*.h')
index 64fdd995776afe5338cc925e1f5011daff6c2cb2..4e7224caf0e77c1ba8effb6965fae3dfcd8dab09 100644 (file)
@@ -23,7 +23,7 @@
 #ifndef ALWAYS_INLINE
 #if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW)
 #define ALWAYS_INLINE inline __attribute__((__always_inline__))
 #ifndef ALWAYS_INLINE
 #if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW)
 #define ALWAYS_INLINE inline __attribute__((__always_inline__))
-#elif COMPILER(MSVC) && defined(NDEBUG)
+#elif (COMPILER(MSVC) || COMPILER(RVCT)) && defined(NDEBUG)
 #define ALWAYS_INLINE __forceinline
 #else
 #define ALWAYS_INLINE inline
 #define ALWAYS_INLINE __forceinline
 #else
 #define ALWAYS_INLINE inline
index 4b261ca0cdbe389b092a63df9c8f3dfd71acbfaf..309c1c411cda15e11ef2bf09c22af1f9585afc67 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2003, 2006, 2007 Apple Inc.  All rights reserved.
 /*
  * Copyright (C) 2003, 2006, 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,7 +33,7 @@
 
 #include <CoreFoundation/CFString.h>
 
 
 #include <CoreFoundation/CFString.h>
 
-#if COMPILER(MSVC) && !PLATFORM(WINCE)
+#if COMPILER(MSVC) && !OS(WINCE)
 #ifndef WINVER
 #define WINVER 0x0500
 #endif
 #ifndef WINVER
 #define WINVER 0x0500
 #endif
 #include <crtdbg.h>
 #endif
 
 #include <crtdbg.h>
 #endif
 
+#if OS(WINCE)
+#include <winbase.h>
+#endif
+
 extern "C" {
 
 WTF_ATTRIBUTE_PRINTF(1, 0)
 extern "C" {
 
 WTF_ATTRIBUTE_PRINTF(1, 0)
@@ -63,7 +68,11 @@ static void vprintf_stderr_common(const char* format, va_list args)
         CFRelease(str);
         CFRelease(cfFormat);
     } else
         CFRelease(str);
         CFRelease(cfFormat);
     } else
+#if OS(SYMBIAN)
+    vfprintf(stdout, format, args);
+#else
     vfprintf(stderr, format, args);
     vfprintf(stderr, format, args);
+#endif
 }
 
 WTF_ATTRIBUTE_PRINTF(1, 2)
 }
 
 WTF_ATTRIBUTE_PRINTF(1, 2)
@@ -77,7 +86,7 @@ static void printf_stderr_common(const char* format, ...)
 
 static void printCallSite(const char* file, int line, const char* function)
 {
 
 static void printCallSite(const char* file, int line, const char* function)
 {
-#if PLATFORM(WIN) && defined _DEBUG
+#if OS(WIN) && !OS(WINCE) && defined _DEBUG
     _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
 #else
     printf_stderr_common("(%s:%d %s)\n", file, line, function);
     _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
 #else
     printf_stderr_common("(%s:%d %s)\n", file, line, function);
index 7e585a5e77f4d52c66dab305c447987df7544de4..365903046f965a6bcb0f4e09dc5c13e812b9fc69 100644 (file)
 #include <inttypes.h>
 #endif
 
 #include <inttypes.h>
 #endif
 
+#if OS(SYMBIAN)
+#include <e32def.h>
+#include <e32debug.h>
+#endif
+
 #ifdef NDEBUG
 #define ASSERTIONS_DISABLED_DEFAULT 1
 #else
 #define ASSERTIONS_DISABLED_DEFAULT 0
 #endif
 
 #ifdef NDEBUG
 #define ASSERTIONS_DISABLED_DEFAULT 1
 #else
 #define ASSERTIONS_DISABLED_DEFAULT 0
 #endif
 
+#if COMPILER(MSVC7) || COMPILER(WINSCW)
+#define HAVE_VARIADIC_MACRO 0
+#else
+#define HAVE_VARIADIC_MACRO 1
+#endif
+
 #ifndef ASSERT_DISABLED
 #define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
 #endif
 
 #ifndef ASSERT_DISABLED
 #define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
 #endif
 
+#ifndef ASSERT_MSG_DISABLED
+#if HAVE(VARIADIC_MACRO)
+#define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT
+#else
+#define ASSERT_MSG_DISABLED 1
+#endif
+#endif
+
 #ifndef ASSERT_ARG_DISABLED
 #define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
 #endif
 
 #ifndef FATAL_DISABLED
 #ifndef ASSERT_ARG_DISABLED
 #define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
 #endif
 
 #ifndef FATAL_DISABLED
+#if HAVE(VARIADIC_MACRO)
 #define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
 #define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
+#else
+#define FATAL_DISABLED 1
+#endif
 #endif
 
 #ifndef ERROR_DISABLED
 #endif
 
 #ifndef ERROR_DISABLED
+#if HAVE(VARIADIC_MACRO)
 #define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
 #define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
+#else
+#define ERROR_DISABLED 1
+#endif
 #endif
 
 #ifndef LOG_DISABLED
 #endif
 
 #ifndef LOG_DISABLED
+#if HAVE(VARIADIC_MACRO)
 #define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
 #define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
+#else
+#define LOG_DISABLED 1
+#endif
 #endif
 
 #if COMPILER(GCC)
 #endif
 
 #if COMPILER(GCC)
@@ -129,15 +160,22 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
 /* CRASH -- gets us into the debugger or the crash reporter -- signals are ignored by the crash reporter so we must do better */
 
 #ifndef CRASH
 /* CRASH -- gets us into the debugger or the crash reporter -- signals are ignored by the crash reporter so we must do better */
 
 #ifndef CRASH
+#if OS(SYMBIAN)
+#define CRASH() do { \
+    __DEBUGGER(); \
+    User::Panic(_L("Webkit CRASH"),0); \
+    } while(false)
+#else
 #define CRASH() do { \
     *(int *)(uintptr_t)0xbbadbeef = 0; \
     ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
 } while(false)
 #endif
 #define CRASH() do { \
     *(int *)(uintptr_t)0xbbadbeef = 0; \
     ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
 } while(false)
 #endif
+#endif
 
 
-/* ASSERT, ASSERT_WITH_MESSAGE, ASSERT_NOT_REACHED */
+/* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED */
 
 
-#if PLATFORM(WINCE) && !PLATFORM(TORCHMOBILE)
+#if OS(WINCE) && !PLATFORM(TORCHMOBILE)
 /* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */
 #include <windows.h>
 #undef min
 /* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */
 #include <windows.h>
 #undef min
@@ -145,15 +183,14 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
 #undef ERROR
 #endif
 
 #undef ERROR
 #endif
 
-#if PLATFORM(WIN_OS)
-/* FIXME: Change to use something other than ASSERT to avoid this conflict with win32. */
+#if OS(WINDOWS) || OS(SYMBIAN)
+/* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
 #undef ASSERT
 #endif
 
 #if ASSERT_DISABLED
 
 #define ASSERT(assertion) ((void)0)
 #undef ASSERT
 #endif
 
 #if ASSERT_DISABLED
 
 #define ASSERT(assertion) ((void)0)
-#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
 #define ASSERT_NOT_REACHED() ((void)0)
 #define ASSERT_UNUSED(variable, assertion) ((void)variable)
 
 #define ASSERT_NOT_REACHED() ((void)0)
 #define ASSERT_UNUSED(variable, assertion) ((void)variable)
 
@@ -165,8 +202,24 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
         CRASH(); \
     } \
 while (0)
         CRASH(); \
     } \
 while (0)
+
+#define ASSERT_NOT_REACHED() do { \
+    WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
+    CRASH(); \
+} while (0)
+
+#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
+
+#endif
+
+/* ASSERT_WITH_MESSAGE */
+
 #if COMPILER(MSVC7)
 #define ASSERT_WITH_MESSAGE(assertion) ((void)0)
 #if COMPILER(MSVC7)
 #define ASSERT_WITH_MESSAGE(assertion) ((void)0)
+#elif COMPILER(WINSCW)
+#define ASSERT_WITH_MESSAGE(assertion, arg...) ((void)0)
+#elif ASSERT_MSG_DISABLED
+#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
 #else
 #define ASSERT_WITH_MESSAGE(assertion, ...) do \
     if (!(assertion)) { \
 #else
 #define ASSERT_WITH_MESSAGE(assertion, ...) do \
     if (!(assertion)) { \
@@ -174,16 +227,9 @@ while (0)
         CRASH(); \
     } \
 while (0)
         CRASH(); \
     } \
 while (0)
-#endif /* COMPILER(MSVC7) */
-#define ASSERT_NOT_REACHED() do { \
-    WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
-    CRASH(); \
-} while (0)
-
-#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
-
 #endif
 #endif
-
+                        
+                        
 /* ASSERT_ARG */
 
 #if ASSERT_ARG_DISABLED
 /* ASSERT_ARG */
 
 #if ASSERT_ARG_DISABLED
@@ -208,10 +254,12 @@ while (0)
 
 /* FATAL */
 
 
 /* FATAL */
 
-#if FATAL_DISABLED
-#define FATAL(...) ((void)0)
-#elif COMPILER(MSVC7)
+#if COMPILER(MSVC7)
 #define FATAL() ((void)0)
 #define FATAL() ((void)0)
+#elif COMPILER(WINSCW)
+#define FATAL(arg...) ((void)0)
+#elif FATAL_DISABLED
+#define FATAL(...) ((void)0)
 #else
 #define FATAL(...) do { \
     WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
 #else
 #define FATAL(...) do { \
     WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
@@ -221,20 +269,24 @@ while (0)
 
 /* LOG_ERROR */
 
 
 /* LOG_ERROR */
 
-#if ERROR_DISABLED
-#define LOG_ERROR(...) ((void)0)
-#elif COMPILER(MSVC7)
+#if COMPILER(MSVC7)
 #define LOG_ERROR() ((void)0)
 #define LOG_ERROR() ((void)0)
+#elif COMPILER(WINSCW)
+#define LOG_ERROR(arg...)  ((void)0)
+#elif ERROR_DISABLED
+#define LOG_ERROR(...) ((void)0)
 #else
 #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
 #endif
 
 /* LOG */
 
 #else
 #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
 #endif
 
 /* LOG */
 
-#if LOG_DISABLED
-#define LOG(channel, ...) ((void)0)
-#elif COMPILER(MSVC7)
+#if COMPILER(MSVC7)
 #define LOG() ((void)0)
 #define LOG() ((void)0)
+#elif COMPILER(WINSCW)
+#define LOG(arg...) ((void)0)
+#elif LOG_DISABLED
+#define LOG(channel, ...) ((void)0)
 #else
 #define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
 #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
 #else
 #define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
 #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
@@ -243,10 +295,12 @@ while (0)
 
 /* LOG_VERBOSE */
 
 
 /* LOG_VERBOSE */
 
-#if LOG_DISABLED
-#define LOG_VERBOSE(channel, ...) ((void)0)
-#elif COMPILER(MSVC7)
+#if COMPILER(MSVC7)
 #define LOG_VERBOSE(channel) ((void)0)
 #define LOG_VERBOSE(channel) ((void)0)
+#elif COMPILER(WINSCW)
+#define LOG_VERBOSE(channel, arg...) ((void)0)
+#elif LOG_DISABLED
+#define LOG_VERBOSE(channel, ...) ((void)0)
 #else
 #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
 #endif
 #else
 #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
 #endif
index 33f0877f06e5510d720cacf1bc1f321033f651ec..f5f5ded8ffe8cf3c1ef7387538c59b57e60437e5 100644 (file)
@@ -26,8 +26,8 @@
 #ifndef ByteArray_h
 #define ByteArray_h
 
 #ifndef ByteArray_h
 #define ByteArray_h
 
-#include "wtf/PassRefPtr.h"
-#include "wtf/RefCounted.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
 
 namespace WTF {
     class ByteArray : public RefCountedBase {
 
 namespace WTF {
     class ByteArray : public RefCountedBase {
@@ -45,6 +45,13 @@ namespace WTF {
             m_data[index] = static_cast<unsigned char>(value + 0.5);
         }
 
             m_data[index] = static_cast<unsigned char>(value + 0.5);
         }
 
+        void set(unsigned index, unsigned char value)
+        {
+            if (index >= m_size)
+                return;
+            m_data[index] = value;
+        }
+
         bool get(unsigned index, unsigned char& result) const
         {
             if (index >= m_size)
         bool get(unsigned index, unsigned char& result) const
         {
             if (index >= m_size)
@@ -53,6 +60,12 @@ namespace WTF {
             return true;
         }
 
             return true;
         }
 
+        unsigned char get(unsigned index) const
+        {
+            ASSERT(index < m_size);
+            return m_data[index];
+        }
+
         unsigned char* data() { return m_data; }
 
         void deref()
         unsigned char* data() { return m_data; }
 
         void deref()
index 103b2a1217411dbc7c9e458675f7406cb927b7af..831616150ac243601aecc8ef8051b2cbd9ec6290 100644 (file)
@@ -36,6 +36,8 @@
 #include <wtf/RefCounted.h>
 #include <wtf/Threading.h>
 
 #include <wtf/RefCounted.h>
 #include <wtf/Threading.h>
 
+#include <wtf/iphone/WebCoreThread.h>
+
 namespace WTF {
 
     // Used to allowing sharing data across classes and threads (like ThreadedSafeShared).
 namespace WTF {
 
     // Used to allowing sharing data across classes and threads (like ThreadedSafeShared).
@@ -51,7 +53,7 @@ namespace WTF {
     // with respect to the original and any other copies.  The underlying m_data is jointly
     // owned by the original instance and all copies.
     template<class T>
     // with respect to the original and any other copies.  The underlying m_data is jointly
     // owned by the original instance and all copies.
     template<class T>
-    class CrossThreadRefCounted : Noncopyable {
+    class CrossThreadRefCounted : public Noncopyable {
     public:
         static PassRefPtr<CrossThreadRefCounted<T> > create(T* data)
         {
     public:
         static PassRefPtr<CrossThreadRefCounted<T> > create(T* data)
         {
@@ -70,10 +72,6 @@ namespace WTF {
             return !m_refCounter.hasOneRef() || (m_threadSafeRefCounter && !m_threadSafeRefCounter->hasOneRef());
         }
 
             return !m_refCounter.hasOneRef() || (m_threadSafeRefCounter && !m_threadSafeRefCounter->hasOneRef());
         }
 
-#ifndef NDEBUG
-        bool mayBePassedToAnotherThread() const { ASSERT(!m_threadId); return m_refCounter.hasOneRef(); }
-#endif
-
     private:
         CrossThreadRefCounted(T* data, ThreadSafeSharedBase* threadedCounter)
             : m_threadSafeRefCounter(threadedCounter)
     private:
         CrossThreadRefCounted(T* data, ThreadSafeSharedBase* threadedCounter)
             : m_threadSafeRefCounter(threadedCounter)
@@ -92,6 +90,12 @@ namespace WTF {
 
         void threadSafeDeref();
 
 
         void threadSafeDeref();
 
+#ifndef NDEBUG
+        bool isOwnedByCurrentThread() const {
+            return !m_threadId || m_threadId == currentThread() || ((isMainThread() || pthread_main_np()) && WebCoreWebThreadIsLockedOrDisabled());
+        }
+#endif
+
         RefCountedBase m_refCounter;
         ThreadSafeSharedBase* m_threadSafeRefCounter;
         T* m_data;
         RefCountedBase m_refCounter;
         ThreadSafeSharedBase* m_threadSafeRefCounter;
         T* m_data;
@@ -103,17 +107,8 @@ namespace WTF {
     template<class T>
     void CrossThreadRefCounted<T>::ref()
     {
     template<class T>
     void CrossThreadRefCounted<T>::ref()
     {
-        
-        // MobileSafari allocates content on the UI thread then
-        // frees it on the Web thread. This is ok. This occurs in a
-        // couple of places. In particular, http://maps.google.com
-        // which uses JS to add an iFrame with an about:blank URL and 
-        // then executes some JS. Much of this work happens on the
-        // main (UI) thread.
-        // Ideally we want to have this assert here:
-        // ASSERT(WebThreadIsLockedOrDisabled())
-        // but then we would need to include code from
-        // WebCore. So just don't do any ASSERTs here.
+        ASSERT(isOwnedByCurrentThread());
+
         m_refCounter.ref();
 #ifndef NDEBUG
         // Store the threadId as soon as the ref count gets to 2.
         m_refCounter.ref();
 #ifndef NDEBUG
         // Store the threadId as soon as the ref count gets to 2.
@@ -129,16 +124,8 @@ namespace WTF {
     template<class T>
     void CrossThreadRefCounted<T>::deref()
     {
     template<class T>
     void CrossThreadRefCounted<T>::deref()
     {
-        // MobileSafari allocates content on the UI thread then
-        // frees it on the Web thread. This is ok. This occurs in a
-        // couple of places. In particular, http://maps.google.com
-        // which uses JS to add an iFrame with an about:blank URL and 
-        // then executes some JS. Much of this work happens on the
-        // main (UI) thread.
-        // Ideally we want to have this assert here:
-        // ASSERT(WebThreadIsLockedOrDisabled())
-        // but then we would need to include code from
-        // WebCore. So just don't do any ASSERTs here.
+        ASSERT(isOwnedByCurrentThread());
+
         if (m_refCounter.derefBase()) {
             threadSafeDeref();
             delete this;
         if (m_refCounter.derefBase()) {
             threadSafeDeref();
             delete this;
@@ -165,10 +152,13 @@ namespace WTF {
     template<class T>
     PassRefPtr<CrossThreadRefCounted<T> > CrossThreadRefCounted<T>::crossThreadCopy()
     {
     template<class T>
     PassRefPtr<CrossThreadRefCounted<T> > CrossThreadRefCounted<T>::crossThreadCopy()
     {
+        ASSERT(isOwnedByCurrentThread());
+
         if (m_threadSafeRefCounter)
             m_threadSafeRefCounter->ref();
         else
             m_threadSafeRefCounter = new ThreadSafeSharedBase(2);
         if (m_threadSafeRefCounter)
             m_threadSafeRefCounter->ref();
         else
             m_threadSafeRefCounter = new ThreadSafeSharedBase(2);
+
         return adoptRef(new CrossThreadRefCounted<T>(m_data, m_threadSafeRefCounter));
     }
 
         return adoptRef(new CrossThreadRefCounted<T>(m_data, m_threadSafeRefCounter));
     }
 
index 38bc4ef6bcff45f255aa3129223dc6cbaad86df9..b2728747bbb51559f10b74a128e44065459d23c0 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
  * Copyright (C) 2008 Google Inc. All rights reserved.
 /*
  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
  * Copyright (C) 2008 Google Inc. All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -32,7 +33,8 @@
 #include "config.h"
 #include "CurrentTime.h"
 
 #include "config.h"
 #include "CurrentTime.h"
 
-#if PLATFORM(WIN_OS)
+#if OS(WINDOWS)
+
 // Windows is first since we want to use hires timers, despite PLATFORM(CF)
 // being defined.
 // If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod.
 // Windows is first since we want to use hires timers, despite PLATFORM(CF)
 // being defined.
 // If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod.
 #include <windows.h>
 #include <math.h>
 #include <stdint.h>
 #include <windows.h>
 #include <math.h>
 #include <stdint.h>
+#include <time.h>
+
+#if USE(QUERY_PERFORMANCE_COUNTER)
+#if OS(WINCE)
+extern "C" time_t mktime(struct tm *t);
+#else
 #include <sys/timeb.h>
 #include <sys/types.h>
 #include <sys/timeb.h>
 #include <sys/types.h>
-#include <time.h>
+#endif
+#endif
+
 #elif PLATFORM(CF)
 #include <CoreFoundation/CFDate.h>
 #elif PLATFORM(GTK)
 #elif PLATFORM(CF)
 #include <CoreFoundation/CFDate.h>
 #elif PLATFORM(GTK)
 #include <sys/time.h>
 #endif
 
 #include <sys/time.h>
 #endif
 
+#if PLATFORM(CHROMIUM)
+#error Chromium uses a different timer implementation
+#endif
+
 namespace WTF {
 
 const double msPerSecond = 1000.0;
 
 namespace WTF {
 
 const double msPerSecond = 1000.0;
 
-#if PLATFORM(WIN_OS)
+#if OS(WINDOWS)
+
+#if USE(QUERY_PERFORMANCE_COUNTER)
 
 static LARGE_INTEGER qpcFrequency;
 static bool syncedTime;
 
 static LARGE_INTEGER qpcFrequency;
 static bool syncedTime;
@@ -107,7 +123,7 @@ static double highResUpTime()
 
 static double lowResUTCTime()
 {
 
 static double lowResUTCTime()
 {
-#if PLATFORM(WINCE)
+#if OS(WINCE)
     SYSTEMTIME systemTime;
     GetSystemTime(&systemTime);
     struct tm tmtime;
     SYSTEMTIME systemTime;
     GetSystemTime(&systemTime);
     struct tm tmtime;
@@ -184,6 +200,55 @@ double currentTime()
     return utc / 1000.0;
 }
 
     return utc / 1000.0;
 }
 
+#else
+
+static double currentSystemTime()
+{
+    FILETIME ft;
+    GetCurrentFT(&ft);
+
+    // As per Windows documentation for FILETIME, copy the resulting FILETIME structure to a
+    // ULARGE_INTEGER structure using memcpy (using memcpy instead of direct assignment can
+    // prevent alignment faults on 64-bit Windows).
+
+    ULARGE_INTEGER t;
+    memcpy(&t, &ft, sizeof(t));
+
+    // Windows file times are in 100s of nanoseconds.
+    // To convert to seconds, we have to divide by 10,000,000, which is more quickly
+    // done by multiplying by 0.0000001.
+
+    // Between January 1, 1601 and January 1, 1970, there were 369 complete years,
+    // of which 89 were leap years (1700, 1800, and 1900 were not leap years).
+    // That is a total of 134774 days, which is 11644473600 seconds.
+
+    return t.QuadPart * 0.0000001 - 11644473600.0;
+}
+
+double currentTime()
+{
+    static bool init = false;
+    static double lastTime;
+    static DWORD lastTickCount;
+    if (!init) {
+        lastTime = currentSystemTime();
+        lastTickCount = GetTickCount();
+        init = true;
+        return lastTime;
+    }
+
+    DWORD tickCountNow = GetTickCount();
+    DWORD elapsed = tickCountNow - lastTickCount;
+    double timeNow = lastTime + (double)elapsed / 1000.;
+    if (elapsed >= 0x7FFFFFFF) {
+        lastTime = timeNow;
+        lastTickCount = tickCountNow;
+    }
+    return timeNow;
+}
+
+#endif // USE(QUERY_PERFORMANCE_COUNTER)
+
 #elif PLATFORM(CF)
 
 double currentTime()
 #elif PLATFORM(CF)
 
 double currentTime()
index 31f1ec8753057991deeb06bb62cab7608621907b..334a6e98a5c46685e394ade369cc1f9d547ed5f5 100644 (file)
 #ifndef CurrentTime_h
 #define CurrentTime_h
 
 #ifndef CurrentTime_h
 #define CurrentTime_h
 
+#include <time.h>
+
 namespace WTF {
 
 namespace WTF {
 
-    // Returns the current system (UTC) time in seconds, starting January 1, 1970.
-    // Precision varies depending on a platform but usually is as good or better 
+    // Returns the current UTC time in seconds, counted from January 1, 1970.
+    // Precision varies depending on platform but is usually as good or better 
     // than a millisecond.
     double currentTime();
 
     // than a millisecond.
     double currentTime();
 
+    // Same thing, in milliseconds.
+    inline double currentTimeMS()
+    {
+        return currentTime() * 1000.0; 
+    }
+
+    inline void getLocalTime(const time_t* localTime, struct tm* localTM)
+    {
+    #if COMPILER(MSVC7) || COMPILER(MINGW) || OS(WINCE)
+        *localTM = *localtime(localTime);
+    #elif COMPILER(MSVC)
+        localtime_s(localTM, localTime);
+    #else
+        localtime_r(localTime, localTM);
+    #endif
+    }
+
 } // namespace WTF
 
 using WTF::currentTime;
 } // namespace WTF
 
 using WTF::currentTime;
index 1d480eeced1a0b112259d5deafbe0a1127e80c33..b9a0207a4c9216a4af333d267dd8f3fe5567a86d 100644 (file)
  * other provisions required by the MPL or the GPL, as the case may be.
  * If you do not delete the provisions above, a recipient may use your
  * version of this file under any of the LGPL, the MPL or the GPL.
  * other provisions required by the MPL or the GPL, as the case may be.
  * If you do not delete the provisions above, a recipient may use your
  * version of this file under any of the LGPL, the MPL or the GPL.
+
+ * Copyright 2006-2008 the V8 project authors. All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "config.h"
  */
 
 #include "config.h"
@@ -61,8 +88,9 @@
 #include <errno.h>
 #endif
 
 #include <errno.h>
 #endif
 
-#if PLATFORM(DARWIN)
-#include <notify.h>
+#if OS(WINCE)
+extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t);
+extern "C" struct tm * localtime(const time_t *timer);
 #endif
 
 #if HAVE(SYS_TIME_H)
 #endif
 
 #if HAVE(SYS_TIME_H)
 #include <sys/timeb.h>
 #endif
 
 #include <sys/timeb.h>
 #endif
 
+#if USE(JSC)
+#include "CallFrame.h"
+#endif
+
 #define NaN std::numeric_limits<double>::quiet_NaN()
 
 #define NaN std::numeric_limits<double>::quiet_NaN()
 
+using namespace WTF;
+
 namespace WTF {
 
 /* Constants */
 namespace WTF {
 
 /* Constants */
@@ -86,6 +120,10 @@ static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0;
 static const double usecPerSec = 1000000.0;
 
 static const double maxUnixTime = 2145859200.0; // 12/31/2037
 static const double usecPerSec = 1000000.0;
 
 static const double maxUnixTime = 2145859200.0; // 12/31/2037
+// ECMAScript asks not to support for a date of which total
+// millisecond value is larger than the following value.
+// See 15.9.1.14 of ECMA-262 5th edition.
+static const double maxECMAScriptTime = 8.64E15;
 
 // Day of year for the first day of each month, where index 0 is January, and day 0 is January 1.
 // First for non-leap years, then for leap years.
 
 // Day of year for the first day of each month, where index 0 is January, and day 0 is January 1.
 // First for non-leap years, then for leap years.
@@ -134,7 +172,7 @@ static inline double msToDays(double ms)
     return floor(ms / msPerDay);
 }
 
     return floor(ms / msPerDay);
 }
 
-static inline int msToYear(double ms)
+int msToYear(double ms)
 {
     int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970);
     double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear);
 {
     int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970);
     double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear);
@@ -145,7 +183,7 @@ static inline int msToYear(double ms)
     return approxYear;
 }
 
     return approxYear;
 }
 
-static inline int dayInYear(double ms, int year)
+int dayInYear(double ms, int year)
 {
     return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year));
 }
 {
     return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year));
 }
@@ -191,7 +229,7 @@ static inline int msToHours(double ms)
     return static_cast<int>(result);
 }
 
     return static_cast<int>(result);
 }
 
-static inline int monthFromDayInYear(int dayInYear, bool leapYear)
+int monthFromDayInYear(int dayInYear, bool leapYear)
 {
     const int d = dayInYear;
     int step;
 {
     const int d = dayInYear;
     int step;
@@ -229,7 +267,7 @@ static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& star
     return (dayInYear <= startDayOfNextMonth);
 }
 
     return (dayInYear <= startDayOfNextMonth);
 }
 
-static inline int dayInMonthFromDayInYear(int dayInYear, bool leapYear)
+int dayInMonthFromDayInYear(int dayInYear, bool leapYear)
 {
     const int d = dayInYear;
     int step;
 {
     const int d = dayInYear;
     int step;
@@ -272,7 +310,7 @@ static inline double timeToMS(double hour, double min, double sec, double ms)
     return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms);
 }
 
     return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms);
 }
 
-static int dateToDayInYear(int year, int month, int day)
+double dateToDaysFrom1970(int year, int month, int day)
 {
     year += month / 12;
 
 {
     year += month / 12;
 
@@ -282,34 +320,13 @@ static int dateToDayInYear(int year, int month, int day)
         --year;
     }
 
         --year;
     }
 
-    int yearday = static_cast<int>(floor(daysFrom1970ToYear(year)));
+    double yearday = floor(daysFrom1970ToYear(year));
+    ASSERT((year >= 1970 && yearday >= 0) || (year < 1970 && yearday < 0));
     int monthday = monthToDayInYear(month, isLeapYear(year));
 
     return yearday + monthday + day - 1;
 }
 
     int monthday = monthToDayInYear(month, isLeapYear(year));
 
     return yearday + monthday + day - 1;
 }
 
-double getCurrentUTCTime()
-{
-    return floor(getCurrentUTCTimeWithMicroseconds());
-}
-
-// Returns current time in milliseconds since 1 Jan 1970.
-double getCurrentUTCTimeWithMicroseconds()
-{
-    return currentTime() * 1000.0; 
-}
-
-void getLocalTime(const time_t* localTime, struct tm* localTM)
-{
-#if COMPILER(MSVC7) || COMPILER(MINGW) || PLATFORM(WINCE)
-    *localTM = *localtime(localTime);
-#elif COMPILER(MSVC)
-    localtime_s(localTM, localTime);
-#else
-    localtime_r(localTime, localTM);
-#endif
-}
-
 // There is a hard limit at 2038 that we currently do not have a workaround
 // for (rdar://problem/5052975).
 static inline int maximumYearForDST()
 // There is a hard limit at 2038 that we currently do not have a workaround
 // for (rdar://problem/5052975).
 static inline int maximumYearForDST()
@@ -323,7 +340,7 @@ static inline int minimumYearForDST()
     // greater than the max year minus 27 (2010), we want to use the max year
     // minus 27 instead, to ensure there is a range of 28 years that all years
     // can map to.
     // greater than the max year minus 27 (2010), we want to use the max year
     // minus 27 instead, to ensure there is a range of 28 years that all years
     // can map to.
-    return std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ;
+    return std::min(msToYear(jsCurrentTime()), maximumYearForDST() - 27) ;
 }
 
 /*
 }
 
 /*
@@ -362,7 +379,11 @@ int equivalentYearForDST(int year)
 
 static int32_t calculateUTCOffset()
 {
 
 static int32_t calculateUTCOffset()
 {
+#if PLATFORM(BREWMP)
+    time_t localTime = static_cast<time_t>(currentTime());
+#else
     time_t localTime = time(0);
     time_t localTime = time(0);
+#endif
     tm localt;
     getLocalTime(&localTime, &localt);
 
     tm localt;
     getLocalTime(&localTime, &localt);
 
@@ -376,57 +397,28 @@ static int32_t calculateUTCOffset()
     localt.tm_wday = 0;
     localt.tm_yday = 0;
     localt.tm_isdst = 0;
     localt.tm_wday = 0;
     localt.tm_yday = 0;
     localt.tm_isdst = 0;
-#if PLATFORM(WIN_OS) || PLATFORM(SOLARIS) || COMPILER(RVCT)
+#if HAVE(TM_GMTOFF)
+    localt.tm_gmtoff = 0;
+#endif
+#if HAVE(TM_ZONE)
+    localt.tm_zone = 0;
+#endif
+    
+#if HAVE(TIMEGM)
+    time_t utcOffset = timegm(&localt) - mktime(&localt);
+#else
     // Using a canned date of 01/01/2009 on platforms with weaker date-handling foo.
     localt.tm_year = 109;
     time_t utcOffset = 1230768000 - mktime(&localt);
     // Using a canned date of 01/01/2009 on platforms with weaker date-handling foo.
     localt.tm_year = 109;
     time_t utcOffset = 1230768000 - mktime(&localt);
-#else
-    localt.tm_zone = 0;
-    localt.tm_gmtoff = 0;
-    time_t utcOffset = timegm(&localt) - mktime(&localt);
 #endif
 
     return static_cast<int32_t>(utcOffset * 1000);
 }
 
 #endif
 
     return static_cast<int32_t>(utcOffset * 1000);
 }
 
-#if PLATFORM(DARWIN)
-static int32_t s_cachedUTCOffset; // In milliseconds. An assumption here is that access to an int32_t variable is atomic on platforms that take this code path.
-static bool s_haveCachedUTCOffset;
-static int s_notificationToken;
-#endif
-
-/*
- * Get the difference in milliseconds between this time zone and UTC (GMT)
- * NOT including DST.
- */
-double getUTCOffset()
-{
-#if PLATFORM(DARWIN)
-    if (s_haveCachedUTCOffset) {
-        int notified;
-        uint32_t status = notify_check(s_notificationToken, &notified);
-        if (status == NOTIFY_STATUS_OK && !notified)
-            return s_cachedUTCOffset;
-    }
-#endif
-
-    int32_t utcOffset = calculateUTCOffset();
-
-#if PLATFORM(DARWIN)
-    // Theoretically, it is possible that several threads will be executing this code at once, in which case we will have a race condition,
-    // and a newer value may be overwritten. In practice, time zones don't change that often.
-    s_cachedUTCOffset = utcOffset;
-#endif
-
-    return utcOffset;
-}
-
 /*
 /*
- * Get the DST offset for the time passed in.  Takes
- * seconds (not milliseconds) and cannot handle dates before 1970
- * on some OS'
+ * Get the DST offset for the time passed in.
  */
  */
-static double getDSTOffsetSimple(double localTimeSeconds, double utcOffset)
+static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset)
 {
     if (localTimeSeconds > maxUnixTime)
         localTimeSeconds = maxUnixTime;
 {
     if (localTimeSeconds > maxUnixTime)
         localTimeSeconds = maxUnixTime;
@@ -455,9 +447,9 @@ static double getDSTOffsetSimple(double localTimeSeconds, double utcOffset)
 }
 
 // Get the DST offset, given a time in UTC
 }
 
 // Get the DST offset, given a time in UTC
-static double getDSTOffset(double ms, double utcOffset)
+static double calculateDSTOffset(double ms, double utcOffset)
 {
 {
-    // On Mac OS X, the call to localtime (see getDSTOffsetSimple) will return historically accurate
+    // On Mac OS X, the call to localtime (see calculateDSTOffsetSimple) will return historically accurate
     // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript
     // standard explicitly dictates that historical information should not be considered when
     // determining DST. For this reason we shift away from years that localtime can handle but would
     // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript
     // standard explicitly dictates that historical information should not be considered when
     // determining DST. For this reason we shift away from years that localtime can handle but would
@@ -469,70 +461,22 @@ static double getDSTOffset(double ms, double utcOffset)
         int dayInYearLocal = dayInYear(ms, year);
         int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear);
         int month = monthFromDayInYear(dayInYearLocal, leapYear);
         int dayInYearLocal = dayInYear(ms, year);
         int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear);
         int month = monthFromDayInYear(dayInYearLocal, leapYear);
-        int day = dateToDayInYear(equivalentYear, month, dayInMonth);
+        double day = dateToDaysFrom1970(equivalentYear, month, dayInMonth);
         ms = (day * msPerDay) + msToMilliseconds(ms);
     }
 
         ms = (day * msPerDay) + msToMilliseconds(ms);
     }
 
-    return getDSTOffsetSimple(ms / msPerSecond, utcOffset);
-}
-
-double gregorianDateTimeToMS(const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
-{
-    int day = dateToDayInYear(t.year + 1900, t.month, t.monthDay);
-    double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds);
-    double result = (day * msPerDay) + ms;
-
-    if (!inputIsUTC) { // convert to UTC
-        double utcOffset = getUTCOffset();
-        result -= utcOffset;
-        result -= getDSTOffset(result, utcOffset);
-    }
-
-    return result;
-}
-
-void msToGregorianDateTime(double ms, bool outputIsUTC, GregorianDateTime& tm)
-{
-    // input is UTC
-    double dstOff = 0.0;
-    const double utcOff = getUTCOffset();
-
-    if (!outputIsUTC) {  // convert to local time
-        dstOff = getDSTOffset(ms, utcOff);
-        ms += dstOff + utcOff;
-    }
-
-    const int year = msToYear(ms);
-    tm.second   =  msToSeconds(ms);
-    tm.minute   =  msToMinutes(ms);
-    tm.hour     =  msToHours(ms);
-    tm.weekDay  =  msToWeekDay(ms);
-    tm.yearDay  =  dayInYear(ms, year);
-    tm.monthDay =  dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year));
-    tm.month    =  monthFromDayInYear(tm.yearDay, isLeapYear(year));
-    tm.year     =  year - 1900;
-    tm.isDST    =  dstOff != 0.0;
-
-    tm.utcOffset = outputIsUTC ? 0 : static_cast<long>((dstOff + utcOff) / msPerSecond);
-    tm.timeZone = NULL;
+    return calculateDSTOffsetSimple(ms / msPerSecond, utcOffset);
 }
 
 void initializeDates()
 {
 #ifndef NDEBUG
     static bool alreadyInitialized;
 }
 
 void initializeDates()
 {
 #ifndef NDEBUG
     static bool alreadyInitialized;
-    ASSERT(!alreadyInitialized++);
+    ASSERT(!alreadyInitialized);
+    alreadyInitialized = true;
 #endif
 
     equivalentYearForDST(2000); // Need to call once to initialize a static used in this function.
 #endif
 
     equivalentYearForDST(2000); // Need to call once to initialize a static used in this function.
-#if PLATFORM(DARWIN)
-    // Register for a notification whenever the time zone changes.
-    uint32_t status = notify_register_check("com.apple.system.timezone", &s_notificationToken);
-    if (status == NOTIFY_STATUS_OK) {
-        s_cachedUTCOffset = calculateUTCOffset();
-        s_haveCachedUTCOffset = true;
-    }
-#endif
 }
 
 static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second)
 }
 
 static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second)
@@ -548,7 +492,7 @@ static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int
 // We follow the recommendation of RFC 2822 to consider all
 // obsolete time zones not listed here equivalent to "-0000".
 static const struct KnownZone {
 // We follow the recommendation of RFC 2822 to consider all
 // obsolete time zones not listed here equivalent to "-0000".
 static const struct KnownZone {
-#if !PLATFORM(WIN_OS)
+#if !OS(WINDOWS)
     const
 #endif
         char tzName[4];
     const
 #endif
         char tzName[4];
@@ -613,8 +557,12 @@ static bool parseLong(const char* string, char** stopPosition, int base, long* r
     return true;
 }
 
     return true;
 }
 
-double parseDateFromNullTerminatedCharacters(const char* dateString)
+// Odd case where 'exec' is allowed to be 0, to accomodate a caller in WebCore.
+static double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset)
 {
 {
+    haveTZ = false;
+    offset = 0;
+
     // This parses a date in the form:
     //     Tuesday, 09-Nov-99 23:12:40 GMT
     // or
     // This parses a date in the form:
     //     Tuesday, 09-Nov-99 23:12:40 GMT
     // or
@@ -815,9 +763,6 @@ double parseDateFromNullTerminatedCharacters(const char* dateString)
         }
     }
 
         }
     }
 
-    bool haveTZ = false;
-    int offset = 0;
-
     // Don't fail if the time zone is missing. 
     // Some websites omit the time zone (4275206).
     if (*dateString) {
     // Don't fail if the time zone is missing. 
     // Some websites omit the time zone (4275206).
     if (*dateString) {
@@ -836,7 +781,7 @@ double parseDateFromNullTerminatedCharacters(const char* dateString)
                 return NaN;
 
             int sgn = (o < 0) ? -1 : 1;
                 return NaN;
 
             int sgn = (o < 0) ? -1 : 1;
-            o = abs(o);
+            o = labs(o);
             if (*dateString != ':') {
                 offset = ((o / 100) * 60 + (o % 100)) * sgn;
             } else { // GMT+05:00
             if (*dateString != ':') {
                 offset = ((o / 100) * 60 + (o % 100)) * sgn;
             } else { // GMT+05:00
@@ -880,33 +825,172 @@ double parseDateFromNullTerminatedCharacters(const char* dateString)
         else
             year += 1900;
     }
         else
             year += 1900;
     }
+    
+    return ymdhmsToSeconds(year, month + 1, day, hour, minute, second) * msPerSecond;
+}
+
+double parseDateFromNullTerminatedCharacters(const char* dateString)
+{
+    bool haveTZ;
+    int offset;
+    double ms = parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset);
+    if (isnan(ms))
+        return NaN;
 
     // fall back to local timezone
     if (!haveTZ) {
 
     // fall back to local timezone
     if (!haveTZ) {
-        GregorianDateTime t;
-        t.monthDay = day;
-        t.month = month;
-        t.year = year - 1900;
-        t.isDST = -1;
-        t.second = second;
-        t.minute = minute;
-        t.hour = hour;
-
-        // Use our gregorianDateTimeToMS() rather than mktime() as the latter can't handle the full year range.
-        return gregorianDateTimeToMS(t, 0, false);
+        double utcOffset = calculateUTCOffset();
+        double dstOffset = calculateDSTOffset(ms, utcOffset);
+        offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute);
     }
     }
-
-    return (ymdhmsToSeconds(year, month + 1, day, hour, minute, second) - (offset * 60.0)) * msPerSecond;
+    return ms - (offset * msPerMinute);
 }
 
 double timeClip(double t)
 {
     if (!isfinite(t))
         return NaN;
 }
 
 double timeClip(double t)
 {
     if (!isfinite(t))
         return NaN;
-    if (fabs(t) > 8.64E15)
+    if (fabs(t) > maxECMAScriptTime)
         return NaN;
     return trunc(t);
 }
         return NaN;
     return trunc(t);
 }
+} // namespace WTF
+
+#if USE(JSC)
+namespace JSC {
+
+// Get the DST offset for the time passed in.
+//
+// NOTE: The implementation relies on the fact that no time zones have
+// more than one daylight savings offset change per month.
+// If this function is called with NaN it returns NaN.
+static double getDSTOffset(ExecState* exec, double ms, double utcOffset)
+{
+    DSTOffsetCache& cache = exec->globalData().dstOffsetCache;
+    double start = cache.start;
+    double end = cache.end;
+
+    if (start <= ms) {
+        // If the time fits in the cached interval, return the cached offset.
+        if (ms <= end) return cache.offset;
+
+        // Compute a possible new interval end.
+        double newEnd = end + cache.increment;
+
+        if (ms <= newEnd) {
+            double endOffset = calculateDSTOffset(newEnd, utcOffset);
+            if (cache.offset == endOffset) {
+                // If the offset at the end of the new interval still matches
+                // the offset in the cache, we grow the cached time interval
+                // and return the offset.
+                cache.end = newEnd;
+                cache.increment = msPerMonth;
+                return endOffset;
+            } else {
+                double offset = calculateDSTOffset(ms, utcOffset);
+                if (offset == endOffset) {
+                    // The offset at the given time is equal to the offset at the
+                    // new end of the interval, so that means that we've just skipped
+                    // the point in time where the DST offset change occurred. Updated
+                    // the interval to reflect this and reset the increment.
+                    cache.start = ms;
+                    cache.end = newEnd;
+                    cache.increment = msPerMonth;
+                } else {
+                    // The interval contains a DST offset change and the given time is
+                    // before it. Adjust the increment to avoid a linear search for
+                    // the offset change point and change the end of the interval.
+                    cache.increment /= 3;
+                    cache.end = ms;
+                }
+                // Update the offset in the cache and return it.
+                cache.offset = offset;
+                return offset;
+            }
+        }
+    }
+
+    // Compute the DST offset for the time and shrink the cache interval
+    // to only contain the time. This allows fast repeated DST offset
+    // computations for the same time.
+    double offset = calculateDSTOffset(ms, utcOffset);
+    cache.offset = offset;
+    cache.start = ms;
+    cache.end = ms;
+    cache.increment = msPerMonth;
+    return offset;
+}
 
 
+/*
+ * Get the difference in milliseconds between this time zone and UTC (GMT)
+ * NOT including DST.
+ */
+double getUTCOffset(ExecState* exec)
+{
+    double utcOffset = exec->globalData().cachedUTCOffset;
+    if (!isnan(utcOffset))
+        return utcOffset;
+    exec->globalData().cachedUTCOffset = calculateUTCOffset();
+    return exec->globalData().cachedUTCOffset;
+}
 
 
-} // namespace WTF
+double gregorianDateTimeToMS(ExecState* exec, const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
+{
+    double day = dateToDaysFrom1970(t.year + 1900, t.month, t.monthDay);
+    double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds);
+    double result = (day * WTF::msPerDay) + ms;
+
+    if (!inputIsUTC) { // convert to UTC
+        double utcOffset = getUTCOffset(exec);
+        result -= utcOffset;
+        result -= getDSTOffset(exec, result, utcOffset);
+    }
+
+    return result;
+}
+
+// input is UTC
+void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, GregorianDateTime& tm)
+{
+    double dstOff = 0.0;
+    double utcOff = 0.0;
+    if (!outputIsUTC) {
+        utcOff = getUTCOffset(exec);
+        dstOff = getDSTOffset(exec, ms, utcOff);
+        ms += dstOff + utcOff;
+    }
+
+    const int year = msToYear(ms);
+    tm.second   =  msToSeconds(ms);
+    tm.minute   =  msToMinutes(ms);
+    tm.hour     =  msToHours(ms);
+    tm.weekDay  =  msToWeekDay(ms);
+    tm.yearDay  =  dayInYear(ms, year);
+    tm.monthDay =  dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year));
+    tm.month    =  monthFromDayInYear(tm.yearDay, isLeapYear(year));
+    tm.year     =  year - 1900;
+    tm.isDST    =  dstOff != 0.0;
+    tm.utcOffset = static_cast<long>((dstOff + utcOff) / WTF::msPerSecond);
+    tm.timeZone = NULL;
+}
+
+double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateString)
+{
+    ASSERT(exec);
+    bool haveTZ;
+    int offset;
+    double ms = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset);
+    if (isnan(ms))
+        return NaN;
+
+    // fall back to local timezone
+    if (!haveTZ) {
+        double utcOffset = getUTCOffset(exec);
+        double dstOffset = getDSTOffset(exec, ms, utcOffset);
+        offset = static_cast<int>((utcOffset + dstOffset) / WTF::msPerMinute);
+    }
+    return ms - (offset * WTF::msPerMinute);
+}
+
+} // namespace JSC
+#endif // USE(JSC)
index 8690a4981231aa190d8ad50cde9ee489b49c118b..033d25e2206688c5f0acfcc0c35d4b485819a88b 100644 (file)
 #ifndef DateMath_h
 #define DateMath_h
 
 #ifndef DateMath_h
 #define DateMath_h
 
-#include <time.h>
+#include <math.h>
 #include <string.h>
 #include <string.h>
+#include <time.h>
+#include <wtf/CurrentTime.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/UnusedParam.h>
 
 namespace WTF {
 
 namespace WTF {
-
-struct GregorianDateTime;
-
 void initializeDates();
 void initializeDates();
-void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&);
-double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC);
-double getUTCOffset();
 int equivalentYearForDST(int year);
 int equivalentYearForDST(int year);
-double getCurrentUTCTime();
-double getCurrentUTCTimeWithMicroseconds();
-void getLocalTime(const time_t*, tm*);
 
 // Not really math related, but this is currently the only shared place to put these.  
 
 // Not really math related, but this is currently the only shared place to put these.  
-double parseDateFromNullTerminatedCharacters(const char*);
+double parseDateFromNullTerminatedCharacters(const char* dateString);
 double timeClip(double);
 
 double timeClip(double);
 
+inline double jsCurrentTime()
+{
+    // JavaScript doesn't recognize fractions of a millisecond.
+    return floor(WTF::currentTimeMS());
+}
+
 const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
 const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
 const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
 const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
@@ -74,9 +74,39 @@ const double msPerSecond = 1000.0;
 const double msPerMinute = 60.0 * 1000.0;
 const double msPerHour = 60.0 * 60.0 * 1000.0;
 const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0;
 const double msPerMinute = 60.0 * 1000.0;
 const double msPerHour = 60.0 * 60.0 * 1000.0;
 const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0;
+const double msPerMonth = 2592000000.0;
 
 
-// Intentionally overridding the default tm of the system
-// Tee members of tm differ on various operating systems.
+// Returns the number of days from 1970-01-01 to the specified date.
+double dateToDaysFrom1970(int year, int month, int day);
+int msToYear(double ms);
+int dayInYear(double ms, int year);
+int monthFromDayInYear(int dayInYear, bool leapYear);
+int dayInMonthFromDayInYear(int dayInYear, bool leapYear);
+
+} // namespace WTF
+
+using WTF::dateToDaysFrom1970;
+using WTF::dayInMonthFromDayInYear;
+using WTF::dayInYear;
+using WTF::minutesPerHour;
+using WTF::monthFromDayInYear;
+using WTF::msPerDay;
+using WTF::msPerSecond;
+using WTF::msToYear;
+using WTF::secondsPerMinute;
+
+#if USE(JSC)
+namespace JSC {
+class ExecState;
+struct GregorianDateTime;
+
+void msToGregorianDateTime(ExecState*, double, bool outputIsUTC, GregorianDateTime&);
+double gregorianDateTimeToMS(ExecState*, const GregorianDateTime&, double, bool inputIsUTC);
+double getUTCOffset(ExecState*);
+double parseDateFromNullTerminatedCharacters(ExecState*, const char* dateString);
+
+// Intentionally overridding the default tm of the system.
+// The members of tm differ on various operating systems.
 struct GregorianDateTime : Noncopyable {
     GregorianDateTime()
         : second(0)
 struct GregorianDateTime : Noncopyable {
     GregorianDateTime()
         : second(0)
@@ -98,7 +128,7 @@ struct GregorianDateTime : Noncopyable {
         delete [] timeZone;
     }
 
         delete [] timeZone;
     }
 
-    GregorianDateTime(const tm& inTm)
+    GregorianDateTime(ExecState* exec, const tm& inTm)
         : second(inTm.tm_sec)
         , minute(inTm.tm_min)
         , hour(inTm.tm_hour)
         : second(inTm.tm_sec)
         , minute(inTm.tm_min)
         , hour(inTm.tm_hour)
@@ -109,14 +139,18 @@ struct GregorianDateTime : Noncopyable {
         , year(inTm.tm_year)
         , isDST(inTm.tm_isdst)
     {
         , year(inTm.tm_year)
         , isDST(inTm.tm_isdst)
     {
-#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !COMPILER(RVCT)
+        UNUSED_PARAM(exec);
+#if HAVE(TM_GMTOFF)
         utcOffset = static_cast<int>(inTm.tm_gmtoff);
         utcOffset = static_cast<int>(inTm.tm_gmtoff);
+#else
+        utcOffset = static_cast<int>(getUTCOffset(exec) / WTF::msPerSecond + (isDST ? WTF::secondsPerHour : 0));
+#endif
 
 
+#if HAVE(TM_ZONE)
         int inZoneSize = strlen(inTm.tm_zone) + 1;
         timeZone = new char[inZoneSize];
         strncpy(timeZone, inTm.tm_zone, inZoneSize);
 #else
         int inZoneSize = strlen(inTm.tm_zone) + 1;
         timeZone = new char[inZoneSize];
         strncpy(timeZone, inTm.tm_zone, inZoneSize);
 #else
-        utcOffset = static_cast<int>(getUTCOffset() / msPerSecond + (isDST ? secondsPerHour : 0));
         timeZone = 0;
 #endif
     }
         timeZone = 0;
 #endif
     }
@@ -136,8 +170,10 @@ struct GregorianDateTime : Noncopyable {
         ret.tm_year  =  year;
         ret.tm_isdst =  isDST;
 
         ret.tm_year  =  year;
         ret.tm_isdst =  isDST;
 
-#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !COMPILER(RVCT)
+#if HAVE(TM_GMTOFF)
         ret.tm_gmtoff = static_cast<long>(utcOffset);
         ret.tm_gmtoff = static_cast<long>(utcOffset);
+#endif
+#if HAVE(TM_ZONE)
         ret.tm_zone = timeZone;
 #endif
 
         ret.tm_zone = timeZone;
 #endif
 
@@ -181,7 +217,7 @@ static inline int gmtoffset(const GregorianDateTime& t)
 {
     return t.utcOffset;
 }
 {
     return t.utcOffset;
 }
-
-} // namespace WTF
+} // namespace JSC
+#endif // USE(JSC)
 
 #endif // DateMath_h
 
 #endif // DateMath_h
index 693e9b78a0b36f10362d962fecae6c96cc5cc0de..541f3a8d243c93d50bf672970a472d118faf6a9e 100644 (file)
 #undef tolower
 #undef toupper
 
 #undef tolower
 #undef toupper
 
-#define isalnum WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isalpha WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isascii WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isblank WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define iscntrl WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isdigit WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isgraph WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define islower WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isprint WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define ispunct WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isspace WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isupper WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isxdigit WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define toascii WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define tolower WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define toupper WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define isalnum isalnum_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define isalpha isalpha_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define isascii isascii_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define isblank isblank_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define iscntrl iscntrl_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define isdigit isdigit_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define isgraph isgraph_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define islower islower_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define isprint isprint_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define ispunct ispunct_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define isspace isspace_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define isupper isupper_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define isxdigit isxdigit_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define toascii toascii_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define tolower tolower_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
+#define toupper toupper_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
 
 #endif
 
 #endif
index 9fcbbc1c483789afa8553a06e67159e9bbe009d0..81b1de070e207fe2effa60bfe78cff20e3091351 100644 (file)
@@ -301,6 +301,16 @@ namespace WTF {
         fastFree(p);
     }
 
         fastFree(p);
     }
 
+    template <typename T>
+    inline void fastDeleteSkippingDestructor(T* p)
+    {
+        if (!p)
+            return;
+
+        fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
+        fastFree(p);
+    }
+
     namespace Internal {
         // This is a support template for fastDeleteArray.
         // This handles the case wherein T has a trivial dtor.
     namespace Internal {
         // This is a support template for fastDeleteArray.
         // This handles the case wherein T has a trivial dtor.
@@ -397,7 +407,7 @@ namespace WTF {
 
 } // namespace WTF
 
 
 } // namespace WTF
 
-// Using WTF::FastAllocBase to avoid using FastAllocBase's explicit qualification by WTF::.
 using WTF::FastAllocBase;
 using WTF::FastAllocBase;
+using WTF::fastDeleteSkippingDestructor;
 
 #endif // FastAllocBase_h
 
 #endif // FastAllocBase_h
index f2843d3745d4609d0d3a5026530f95d88594cf32..306d025611de99d337f86936494c9c50c153860a 100644 (file)
@@ -1,6 +1,6 @@
 // Copyright (c) 2005, 2007, Google Inc.
 // All rights reserved.
 // Copyright (c) 2005, 2007, Google Inc.
 // All rights reserved.
-// Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
 // 
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // 
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 #endif
 #endif
 
 #endif
 #endif
 
-#if !defined(USE_SYSTEM_MALLOC) && defined(NDEBUG)
+#if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) && defined(NDEBUG)
 #define FORCE_SYSTEM_MALLOC 0
 #else
 #define FORCE_SYSTEM_MALLOC 1
 #endif
 
 #define FORCE_SYSTEM_MALLOC 0
 #else
 #define FORCE_SYSTEM_MALLOC 1
 #endif
 
-
 // Use a background thread to periodically scavenge memory to release back to the system
 // https://bugs.webkit.org/show_bug.cgi?id=27900: don't turn this on for Tiger until we have figured out why it caused a crash.
 #define USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY 0
 // Use a background thread to periodically scavenge memory to release back to the system
 // https://bugs.webkit.org/show_bug.cgi?id=27900: don't turn this on for Tiger until we have figured out why it caused a crash.
 #define USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY 0
@@ -111,11 +110,13 @@ static void initializeIsForbiddenKey()
   pthread_key_create(&isForbiddenKey, 0);
 }
 
   pthread_key_create(&isForbiddenKey, 0);
 }
 
+#if !ASSERT_DISABLED
 static bool isForbidden()
 {
     pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey);
     return !!pthread_getspecific(isForbiddenKey);
 }
 static bool isForbidden()
 {
     pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey);
     return !!pthread_getspecific(isForbiddenKey);
 }
+#endif
 
 void fastMallocForbid()
 {
 
 void fastMallocForbid()
 {
@@ -174,11 +175,22 @@ void* fastZeroedMalloc(size_t n)
     memset(result, 0, n);
     return result;
 }
     memset(result, 0, n);
     return result;
 }
+
+char* fastStrDup(const char* src)
+{
+    int len = strlen(src) + 1;
+    char* dup = static_cast<char*>(fastMalloc(len));
+
+    if (dup)
+        memcpy(dup, src, len);
+
+    return dup;
+}
     
     
-void* tryFastZeroedMalloc(size_t n) 
+TryMallocReturnValue tryFastZeroedMalloc(size_t n) 
 {
 {
-    void* result = tryFastMalloc(n);
-    if (!result)
+    void* result;
+    if (!tryFastMalloc(n).getValue(result))
         return 0;
     memset(result, 0, n);
     return result;
         return 0;
     memset(result, 0, n);
     return result;
@@ -188,16 +200,9 @@ void* tryFastZeroedMalloc(size_t n)
 
 #if FORCE_SYSTEM_MALLOC
 
 
 #if FORCE_SYSTEM_MALLOC
 
-#include <stdlib.h>
-#if !PLATFORM(WIN_OS)
-    #include <pthread.h>
-#else
-    #include "windows.h"
-#endif
-
 namespace WTF {
 
 namespace WTF {
 
-void* tryFastMalloc(size_t n) 
+TryMallocReturnValue tryFastMalloc(size_t n) 
 {
     ASSERT(!isForbidden());
 
 {
     ASSERT(!isForbidden());
 
@@ -223,7 +228,9 @@ void* fastMalloc(size_t n)
     ASSERT(!isForbidden());
 
 #if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
     ASSERT(!isForbidden());
 
 #if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    void* result = tryFastMalloc(n);
+    TryMallocReturnValue returnValue = tryFastMalloc(n);
+    void* result;
+    returnValue.getValue(result);
 #else
     void* result = malloc(n);
 #endif
 #else
     void* result = malloc(n);
 #endif
@@ -233,7 +240,7 @@ void* fastMalloc(size_t n)
     return result;
 }
 
     return result;
 }
 
-void* tryFastCalloc(size_t n_elements, size_t element_size)
+TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size)
 {
     ASSERT(!isForbidden());
 
 {
     ASSERT(!isForbidden());
 
@@ -261,7 +268,9 @@ void* fastCalloc(size_t n_elements, size_t element_size)
     ASSERT(!isForbidden());
 
 #if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
     ASSERT(!isForbidden());
 
 #if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    void* result = tryFastCalloc(n_elements, element_size);
+    TryMallocReturnValue returnValue = tryFastCalloc(n_elements, element_size);
+    void* result;
+    returnValue.getValue(result);
 #else
     void* result = calloc(n_elements, element_size);
 #endif
 #else
     void* result = calloc(n_elements, element_size);
 #endif
@@ -288,7 +297,7 @@ void fastFree(void* p)
 #endif
 }
 
 #endif
 }
 
-void* tryFastRealloc(void* p, size_t n)
+TryMallocReturnValue tryFastRealloc(void* p, size_t n)
 {
     ASSERT(!isForbidden());
 
 {
     ASSERT(!isForbidden());
 
@@ -320,7 +329,9 @@ void* fastRealloc(void* p, size_t n)
     ASSERT(!isForbidden());
 
 #if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
     ASSERT(!isForbidden());
 
 #if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    void* result = tryFastRealloc(p, n);
+    TryMallocReturnValue returnValue = tryFastRealloc(p, n);
+    void* result;
+    returnValue.getValue(result);
 #else
     void* result = realloc(p, n);
 #endif
 #else
     void* result = realloc(p, n);
 #endif
@@ -340,7 +351,7 @@ FastMallocStatistics fastMallocStatistics()
 
 } // namespace WTF
 
 
 } // namespace WTF
 
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 // This symbol is present in the JavaScriptCore exports file even when FastMalloc is disabled.
 // It will never be used in this case, so it's type and value are less interesting than its presence.
 extern "C" const int jscore_fastmalloc_introspection = 0;
 // This symbol is present in the JavaScriptCore exports file even when FastMalloc is disabled.
 // It will never be used in this case, so it's type and value are less interesting than its presence.
 extern "C" const int jscore_fastmalloc_introspection = 0;
@@ -370,6 +381,9 @@ extern "C" const int jscore_fastmalloc_introspection = 0;
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdio.h>
+#if OS(UNIX)
+#include <unistd.h>
+#endif
 #if COMPILER(MSVC)
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #if COMPILER(MSVC)
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
@@ -379,11 +393,16 @@ extern "C" const int jscore_fastmalloc_introspection = 0;
 
 #if WTF_CHANGES
 
 
 #if WTF_CHANGES
 
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 #include "MallocZoneSupport.h"
 #include <wtf/HashSet.h>
 #include "MallocZoneSupport.h"
 #include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+#endif
+#if HAVE(DISPATCH_H)
+#include <dispatch/dispatch.h>
 #endif
 
 #endif
 
+
 #ifndef PRIuS
 #define PRIuS "zu"
 #endif
 #ifndef PRIuS
 #define PRIuS "zu"
 #endif
@@ -392,7 +411,7 @@ extern "C" const int jscore_fastmalloc_introspection = 0;
 // call to the function on Mac OS X, and it's used in performance-critical code. So we
 // use a function pointer. But that's not necessarily faster on other platforms, and we had
 // problems with this technique on Windows, so we'll do this only on Mac OS X.
 // call to the function on Mac OS X, and it's used in performance-critical code. So we
 // use a function pointer. But that's not necessarily faster on other platforms, and we had
 // problems with this technique on Windows, so we'll do this only on Mac OS X.
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 static void* (*pthread_getspecific_function_pointer)(pthread_key_t) = pthread_getspecific;
 #define pthread_getspecific(key) pthread_getspecific_function_pointer(key)
 #endif
 static void* (*pthread_getspecific_function_pointer)(pthread_key_t) = pthread_getspecific;
 #define pthread_getspecific(key) pthread_getspecific_function_pointer(key)
 #endif
@@ -420,7 +439,7 @@ namespace WTF {
 #define MESSAGE LOG_ERROR
 #define CHECK_CONDITION ASSERT
 
 #define MESSAGE LOG_ERROR
 #define CHECK_CONDITION ASSERT
 
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 class Span;
 class TCMalloc_Central_FreeListPadded;
 class TCMalloc_PageHeap;
 class Span;
 class TCMalloc_Central_FreeListPadded;
 class TCMalloc_PageHeap;
@@ -536,7 +555,7 @@ static const size_t kNumClasses = 68;
 static const size_t kPageMapBigAllocationThreshold = 128 << 20;
 
 // Minimum number of pages to fetch from system at a time.  Must be
 static const size_t kPageMapBigAllocationThreshold = 128 << 20;
 
 // Minimum number of pages to fetch from system at a time.  Must be
-// significantly bigger than kBlockSize to amortize system-call
+// significantly bigger than kPageSize to amortize system-call
 // overhead, and also to reduce external fragementation.  Also, we
 // should keep this value big because various incarnations of Linux
 // have small limits on the number of mmap() regions per
 // overhead, and also to reduce external fragementation.  Also, we
 // should keep this value big because various incarnations of Linux
 // have small limits on the number of mmap() regions per
@@ -977,7 +996,7 @@ class PageHeapAllocator {
 
   int inuse() const { return inuse_; }
 
 
   int inuse() const { return inuse_; }
 
-#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
+#if defined(WTF_CHANGES) && OS(DARWIN)
   template <class Recorder>
   void recordAdministrativeRegions(Recorder& recorder, const RemoteMemoryReader& reader)
   {
   template <class Recorder>
   void recordAdministrativeRegions(Recorder& recorder, const RemoteMemoryReader& reader)
   {
@@ -1159,7 +1178,7 @@ template <int BITS> class MapSelector {
 };
 
 #if defined(WTF_CHANGES)
 };
 
 #if defined(WTF_CHANGES)
-#if PLATFORM(X86_64)
+#if CPU(X86_64)
 // On all known X86-64 platforms, the upper 16 bits are always unused and therefore 
 // can be excluded from the PageMap key.
 // See http://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
 // On all known X86-64 platforms, the upper 16 bits are always unused and therefore 
 // can be excluded from the PageMap key.
 // See http://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
@@ -1210,7 +1229,7 @@ static const int kScavengeTimerDelayInSeconds = 5;
 static const size_t kMinimumFreeCommittedPageCount = 512;
 
 // During a scavenge, we'll release up to a fraction of the free committed pages.
 static const size_t kMinimumFreeCommittedPageCount = 512;
 
 // During a scavenge, we'll release up to a fraction of the free committed pages.
-#if PLATFORM(WIN)
+#if OS(WINDOWS)
 // We are slightly less aggressive in releasing memory on Windows due to performance reasons.
 static const int kMaxScavengeAmountFactor = 3;
 #else
 // We are slightly less aggressive in releasing memory on Windows due to performance reasons.
 static const int kMaxScavengeAmountFactor = 3;
 #else
@@ -1359,26 +1378,34 @@ class TCMalloc_PageHeap {
   // Index of last free list we scavenged
   size_t scavenge_index_;
   
   // Index of last free list we scavenged
   size_t scavenge_index_;
   
-#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
+#if defined(WTF_CHANGES) && OS(DARWIN)
   friend class FastMallocZone;
 #endif
 
 #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
   friend class FastMallocZone;
 #endif
 
 #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-  static NO_RETURN void* runScavengerThread(void*);
+  void initializeScavenger();
+  ALWAYS_INLINE void signalScavenger();
+  void scavenge();
+  ALWAYS_INLINE bool shouldContinueScavenging() const;
 
 
+#if !HAVE(DISPATCH_H)
+  static NO_RETURN void* runScavengerThread(void*);
   NO_RETURN void scavengerThread();
 
   NO_RETURN void scavengerThread();
 
-  void scavenge();
-
-  inline bool shouldContinueScavenging() const;
+  // Keeps track of whether the background thread is actively scavenging memory every kScavengeTimerDelayInSeconds, or
+  // it's blocked waiting for more pages to be deleted.
+  bool m_scavengeThreadActive;
 
   pthread_mutex_t m_scavengeMutex;
 
   pthread_mutex_t m_scavengeMutex;
-
   pthread_cond_t m_scavengeCondition;
   pthread_cond_t m_scavengeCondition;
+#else // !HAVE(DISPATCH_H)
+  void periodicScavenge();
+
+  dispatch_queue_t m_scavengeQueue;
+  dispatch_source_t m_scavengeTimer;
+  bool m_scavengingScheduled;
+#endif
 
 
-  // Keeps track of whether the background thread is actively scavenging memory every kScavengeTimerDelayInSeconds, or
-  // it's blocked waiting for more pages to be deleted.
-  bool m_scavengeThreadActive;
 #endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
 };
 
 #endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
 };
 
@@ -1406,15 +1433,23 @@ void TCMalloc_PageHeap::init()
   }
 
 #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
   }
 
 #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+  initializeScavenger();
+#endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+}
+
+#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
+
+#if !HAVE(DISPATCH_H)
+
+void TCMalloc_PageHeap::initializeScavenger()
+{
   pthread_mutex_init(&m_scavengeMutex, 0);
   pthread_cond_init(&m_scavengeCondition, 0);
   m_scavengeThreadActive = true;
   pthread_t thread;
   pthread_create(&thread, 0, runScavengerThread, this);
   pthread_mutex_init(&m_scavengeMutex, 0);
   pthread_cond_init(&m_scavengeCondition, 0);
   m_scavengeThreadActive = true;
   pthread_t thread;
   pthread_create(&thread, 0, runScavengerThread, this);
-#endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
 }
 
 }
 
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
 void* TCMalloc_PageHeap::runScavengerThread(void* context)
 {
   static_cast<TCMalloc_PageHeap*>(context)->scavengerThread();
 void* TCMalloc_PageHeap::runScavengerThread(void* context)
 {
   static_cast<TCMalloc_PageHeap*>(context)->scavengerThread();
@@ -1424,6 +1459,34 @@ void* TCMalloc_PageHeap::runScavengerThread(void* context)
 #endif
 }
 
 #endif
 }
 
+ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger()
+{
+  if (!m_scavengeThreadActive && shouldContinueScavenging())
+    pthread_cond_signal(&m_scavengeCondition);
+}
+
+#else // !HAVE(DISPATCH_H)
+
+void TCMalloc_PageHeap::initializeScavenger()
+{
+  m_scavengeQueue = dispatch_queue_create("com.apple.JavaScriptCore.FastMallocSavenger", NULL);
+  m_scavengeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, m_scavengeQueue);
+  dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, kScavengeTimerDelayInSeconds * NSEC_PER_SEC);
+  dispatch_source_set_timer(m_scavengeTimer, startTime, kScavengeTimerDelayInSeconds * NSEC_PER_SEC, 1000 * NSEC_PER_USEC);
+  dispatch_source_set_event_handler(m_scavengeTimer, ^{ periodicScavenge(); });
+  m_scavengingScheduled = false;
+}
+
+ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger()
+{
+  if (!m_scavengingScheduled && shouldContinueScavenging()) {
+    m_scavengingScheduled = true;
+    dispatch_resume(m_scavengeTimer);
+  }
+}
+
+#endif
+
 void TCMalloc_PageHeap::scavenge() 
 {
     // If we have to commit memory in the last 5 seconds, it means we don't have enough free committed pages
 void TCMalloc_PageHeap::scavenge() 
 {
     // If we have to commit memory in the last 5 seconds, it means we don't have enough free committed pages
@@ -1459,7 +1522,7 @@ void TCMalloc_PageHeap::scavenge()
     free_committed_pages_ -= pagesDecommitted;
 }
 
     free_committed_pages_ -= pagesDecommitted;
 }
 
-inline bool TCMalloc_PageHeap::shouldContinueScavenging() const 
+ALWAYS_INLINE bool TCMalloc_PageHeap::shouldContinueScavenging() const 
 {
     return free_committed_pages_ > kMinimumFreeCommittedPageCount; 
 }
 {
     return free_committed_pages_ > kMinimumFreeCommittedPageCount; 
 }
@@ -1721,8 +1784,7 @@ inline void TCMalloc_PageHeap::Delete(Span* span) {
   }
 
   // Make sure the scavenge thread becomes active if we have enough freed pages to release some back to the system.
   }
 
   // Make sure the scavenge thread becomes active if we have enough freed pages to release some back to the system.
-  if (!m_scavengeThreadActive && shouldContinueScavenging())
-      pthread_cond_signal(&m_scavengeCondition);
+  signalScavenger();
 #else
   IncrementalScavenge(n);
 #endif
 #else
   IncrementalScavenge(n);
 #endif
@@ -2268,7 +2330,9 @@ static inline TCMalloc_PageHeap* getPageHeap()
 #define pageheap getPageHeap()
 
 #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
 #define pageheap getPageHeap()
 
 #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-#if PLATFORM(WIN)
+
+#if !HAVE(DISPATCH_H)
+#if OS(WINDOWS)
 static void sleep(unsigned seconds)
 {
     ::Sleep(seconds * 1000);
 static void sleep(unsigned seconds)
 {
     ::Sleep(seconds * 1000);
@@ -2297,6 +2361,23 @@ void TCMalloc_PageHeap::scavengerThread()
       }
   }
 }
       }
   }
 }
+
+#else
+
+void TCMalloc_PageHeap::periodicScavenge()
+{
+  {
+    SpinLockHolder h(&pageheap_lock);
+    pageheap->scavenge();
+  }
+
+  if (!shouldContinueScavenging()) {
+    m_scavengingScheduled = false;
+    dispatch_suspend(m_scavengeTimer);
+  }
+}
+#endif // HAVE(DISPATCH_H)
+
 #endif
 
 // If TLS is available, we also store a copy
 #endif
 
 // If TLS is available, we also store a copy
@@ -2386,7 +2467,7 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::ReleaseToSpans(void* object) {
   // The following check is expensive, so it is disabled by default
   if (false) {
     // Check that object does not occur in list
   // The following check is expensive, so it is disabled by default
   if (false) {
     // Check that object does not occur in list
-    int got = 0;
+    unsigned got = 0;
     for (void* p = span->objects; p != NULL; p = *((void**) p)) {
       ASSERT(p != object);
       got++;
     for (void* p = span->objects; p != NULL; p = *((void**) p)) {
       ASSERT(p != object);
       got++;
@@ -2806,7 +2887,7 @@ void TCMalloc_ThreadCache::InitModule() {
     }
     pageheap->init();
     phinited = 1;
     }
     pageheap->init();
     phinited = 1;
-#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
+#if defined(WTF_CHANGES) && OS(DARWIN)
     FastMallocZone::init();
 #endif
   }
     FastMallocZone::init();
 #endif
   }
@@ -3580,7 +3661,7 @@ void* fastMalloc(size_t size)
     return malloc<true>(size);
 }
 
     return malloc<true>(size);
 }
 
-void* tryFastMalloc(size_t size)
+TryMallocReturnValue tryFastMalloc(size_t size)
 {
     return malloc<false>(size);
 }
 {
     return malloc<false>(size);
 }
@@ -3641,7 +3722,7 @@ void* fastCalloc(size_t n, size_t elem_size)
     return calloc<true>(n, elem_size);
 }
 
     return calloc<true>(n, elem_size);
 }
 
-void* tryFastCalloc(size_t n, size_t elem_size)
+TryMallocReturnValue tryFastCalloc(size_t n, size_t elem_size)
 {
     return calloc<false>(n, elem_size);
 }
 {
     return calloc<false>(n, elem_size);
 }
@@ -3705,7 +3786,7 @@ void* fastRealloc(void* old_ptr, size_t new_size)
     return realloc<true>(old_ptr, new_size);
 }
 
     return realloc<true>(old_ptr, new_size);
 }
 
-void* tryFastRealloc(void* old_ptr, size_t new_size)
+TryMallocReturnValue tryFastRealloc(void* old_ptr, size_t new_size)
 {
     return realloc<false>(old_ptr, new_size);
 }
 {
     return realloc<false>(old_ptr, new_size);
 }
@@ -3785,7 +3866,7 @@ void* realloc(void* old_ptr, size_t new_size) {
     return new_ptr;
   } else {
 #if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
     return new_ptr;
   } else {
 #if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    old_ptr = pByte + sizeof(AllocAlignmentInteger);  // Set old_ptr back to the user pointer.
+    old_ptr = static_cast<AllocAlignmentInteger*>(old_ptr) + 1; // Set old_ptr back to the user pointer.
 #endif
     return old_ptr;
   }
 #endif
     return old_ptr;
   }
@@ -4004,7 +4085,7 @@ void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride;
 
 #endif
 
 
 #endif
 
-#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
+#if defined(WTF_CHANGES) && OS(DARWIN)
 
 class FreeObjectFinder {
     const RemoteMemoryReader& m_reader;
 
 class FreeObjectFinder {
     const RemoteMemoryReader& m_reader;
@@ -4287,7 +4368,7 @@ extern "C" {
 malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enumerate, &FastMallocZone::goodSize, &FastMallocZone::check, &FastMallocZone::print,
     &FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics
 
 malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enumerate, &FastMallocZone::goodSize, &FastMallocZone::check, &FastMallocZone::print,
     &FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics
 
-#if !PLATFORM(IPHONE_SIMULATOR)
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) || PLATFORM(IPHONE)
     , 0 // zone_locked will not be called on the zone unless it advertises itself as version five or higher.
 #endif
 
     , 0 // zone_locked will not be called on the zone unless it advertises itself as version five or higher.
 #endif
 
index 61ebe327e433758555a1c331fbf8f726a9cc3d67..74d43070aa3326455466b151373c540ba8b11236 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 #define WTF_FastMalloc_h
 
 #include "Platform.h"
 #define WTF_FastMalloc_h
 
 #include "Platform.h"
+#include "PossiblyNull.h"
 #include <stdlib.h>
 #include <new>
 
 namespace WTF {
 
     // These functions call CRASH() if an allocation fails.
 #include <stdlib.h>
 #include <new>
 
 namespace WTF {
 
     // These functions call CRASH() if an allocation fails.
-    void* fastMalloc(size_t n);
-    void* fastZeroedMalloc(size_t n);
-    void* fastCalloc(size_t n_elements, size_t element_size);
-    void* fastRealloc(void* p, size_t n);
+    void* fastMalloc(size_t);
+    void* fastZeroedMalloc(size_t);
+    void* fastCalloc(size_t numElements, size_t elementSize);
+    void* fastRealloc(void*, size_t);
+    char* fastStrDup(const char*);
+
+    struct TryMallocReturnValue {
+        TryMallocReturnValue(void* data)
+            : m_data(data)
+        {
+        }
+        TryMallocReturnValue(const TryMallocReturnValue& source)
+            : m_data(source.m_data)
+        {
+            source.m_data = 0;
+        }
+        ~TryMallocReturnValue() { ASSERT(!m_data); }
+        template <typename T> bool getValue(T& data) WARN_UNUSED_RETURN;
+        template <typename T> operator PossiblyNull<T>()
+        { 
+            T value; 
+            getValue(value); 
+            return PossiblyNull<T>(value);
+        } 
+    private:
+        mutable void* m_data;
+    };
+    
+    template <typename T> bool TryMallocReturnValue::getValue(T& data)
+    {
+        union u { void* data; T target; } res;
+        res.data = m_data;
+        data = res.target;
+        bool returnValue = !!m_data;
+        m_data = 0;
+        return returnValue;
+    }
 
 
-    // These functions return NULL if an allocation fails.
-    void* tryFastMalloc(size_t n);
-    void* tryFastZeroedMalloc(size_t n);
-    void* tryFastCalloc(size_t n_elements, size_t element_size);
-    void* tryFastRealloc(void* p, size_t n);
+    TryMallocReturnValue tryFastMalloc(size_t n);
+    TryMallocReturnValue tryFastZeroedMalloc(size_t n);
+    TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size);
+    TryMallocReturnValue tryFastRealloc(void* p, size_t n);
 
 
-    void fastFree(void* p);
+    void fastFree(void*);
 
 #ifndef NDEBUG    
     void fastMallocForbid();
 
 #ifndef NDEBUG    
     void fastMallocForbid();
@@ -156,38 +189,53 @@ using WTF::tryFastZeroedMalloc;
 using WTF::tryFastCalloc;
 using WTF::tryFastRealloc;
 using WTF::fastFree;
 using WTF::tryFastCalloc;
 using WTF::tryFastRealloc;
 using WTF::fastFree;
+using WTF::fastStrDup;
 
 #ifndef NDEBUG    
 using WTF::fastMallocForbid;
 using WTF::fastMallocAllow;
 #endif
 
 
 #ifndef NDEBUG    
 using WTF::fastMallocForbid;
 using WTF::fastMallocAllow;
 #endif
 
-#if COMPILER(GCC) && PLATFORM(DARWIN)
+#if COMPILER(GCC) && OS(DARWIN)
 #define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline))
 #elif COMPILER(GCC)
 #define WTF_PRIVATE_INLINE inline __attribute__((always_inline))
 #define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline))
 #elif COMPILER(GCC)
 #define WTF_PRIVATE_INLINE inline __attribute__((always_inline))
-#elif COMPILER(MSVC)
+#elif COMPILER(MSVC) || COMPILER(RVCT)
 #define WTF_PRIVATE_INLINE __forceinline
 #else
 #define WTF_PRIVATE_INLINE inline
 #endif
 
 #define WTF_PRIVATE_INLINE __forceinline
 #else
 #define WTF_PRIVATE_INLINE inline
 #endif
 
-#ifndef _CRTDBG_MAP_ALLOC
+#if !defined(_CRTDBG_MAP_ALLOC) && !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC)
+
+// The nothrow functions here are actually not all that helpful, because fastMalloc will
+// call CRASH() rather than returning 0, and returning 0 is what nothrow is all about.
+// But since WebKit code never uses exceptions or nothrow at all, this is probably OK.
+// Long term we will adopt FastAllocBase.h everywhere, and and replace this with
+// debug-only code to make sure we don't use the system malloc via the default operator
+// new by accident.
 
 
-#if !defined(USE_SYSTEM_MALLOC) || !(USE_SYSTEM_MALLOC)
-WTF_PRIVATE_INLINE void* operator new(size_t s) { return fastMalloc(s); }
-WTF_PRIVATE_INLINE void operator delete(void* p) { fastFree(p); }
-WTF_PRIVATE_INLINE void* operator new[](size_t s) { return fastMalloc(s); }
-WTF_PRIVATE_INLINE void operator delete[](void* p) { fastFree(p); }
+// We musn't customize the global operator new and delete for the Qt port.
+#if !PLATFORM(QT)
 
 
-#if PLATFORM(WINCE)
-WTF_PRIVATE_INLINE void* operator new(size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); }
+#if COMPILER(MSVC)
+#pragma warning(push)
+#pragma warning(disable: 4290) // Disable the C++ exception specification ignored warning.
+#endif
+WTF_PRIVATE_INLINE void* operator new(size_t size) throw (std::bad_alloc) { return fastMalloc(size); }
+WTF_PRIVATE_INLINE void* operator new(size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); }
+WTF_PRIVATE_INLINE void operator delete(void* p) throw() { fastFree(p); }
 WTF_PRIVATE_INLINE void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); }
 WTF_PRIVATE_INLINE void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); }
-WTF_PRIVATE_INLINE void* operator new[](size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); }
+WTF_PRIVATE_INLINE void* operator new[](size_t size) throw (std::bad_alloc) { return fastMalloc(size); }
+WTF_PRIVATE_INLINE void* operator new[](size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); }
+WTF_PRIVATE_INLINE void operator delete[](void* p) throw() { fastFree(p); }
 WTF_PRIVATE_INLINE void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); }
 WTF_PRIVATE_INLINE void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); }
+#if COMPILER(MSVC)
+#pragma warning(pop)
 #endif
 #endif
+
 #endif
 
 #endif
 
-#endif // _CRTDBG_MAP_ALLOC
+#endif
 
 #endif /* WTF_FastMalloc_h */
 
 #endif /* WTF_FastMalloc_h */
index 67dc3be1d31c6d5e33c75cec76d7b9ad980f2230..448de7d5a5ebacaafa64ff2dfac9b46ff422d06d 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (C) 2006 Apple Computer, Inc.
+ *  Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -27,6 +27,7 @@ namespace WTF {
     template<typename T> class ListRefPtr;
     template<typename T> class OwnArrayPtr;
     template<typename T> class OwnPtr;
     template<typename T> class ListRefPtr;
     template<typename T> class OwnArrayPtr;
     template<typename T> class OwnPtr;
+    template<typename T> class PassOwnPtr;
     template<typename T> class PassRefPtr;
     template<typename T> class RefPtr;
     template<typename T, size_t inlineCapacity> class Vector;
     template<typename T> class PassRefPtr;
     template<typename T> class RefPtr;
     template<typename T, size_t inlineCapacity> class Vector;
@@ -35,9 +36,9 @@ namespace WTF {
 using WTF::ListRefPtr;
 using WTF::OwnArrayPtr;
 using WTF::OwnPtr;
 using WTF::ListRefPtr;
 using WTF::OwnArrayPtr;
 using WTF::OwnPtr;
+using WTF::PassOwnPtr;
 using WTF::PassRefPtr;
 using WTF::RefPtr;
 using WTF::Vector;
 
 #endif // WTF_Forward_h
 using WTF::PassRefPtr;
 using WTF::RefPtr;
 using WTF::Vector;
 
 #endif // WTF_Forward_h
-
diff --git a/wtf/GOwnPtr.cpp b/wtf/GOwnPtr.cpp
deleted file mode 100644 (file)
index 432885f..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2008 Collabora Ltd.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "config.h"
-#include "GOwnPtr.h"
-
-namespace WTF {
-
-template <> void freeOwnedGPtr<GError>(GError* ptr)
-{
-    if (ptr)
-        g_error_free(ptr);
-}
-
-template <> void freeOwnedGPtr<GList>(GList* ptr)
-{
-    g_list_free(ptr);
-}
-
-template <> void freeOwnedGPtr<GCond>(GCond* ptr)
-{
-    if (ptr)
-        g_cond_free(ptr);
-}
-
-template <> void freeOwnedGPtr<GMutex>(GMutex* ptr)
-{
-    if (ptr)
-        g_mutex_free(ptr);
-}
-
-template <> void freeOwnedGPtr<GPatternSpec>(GPatternSpec* ptr)
-{
-    if (ptr)
-        g_pattern_spec_free(ptr);
-}
-
-template <> void freeOwnedGPtr<GDir>(GDir* ptr)
-{
-    if (ptr)
-        g_dir_close(ptr);
-}
-
-template <> void freeOwnedGPtr<GHashTable>(GHashTable* ptr)
-{
-    if (ptr)
-        g_hash_table_unref(ptr);
-}
-
-} // namespace WTF
diff --git a/wtf/GOwnPtr.h b/wtf/GOwnPtr.h
deleted file mode 100644 (file)
index 8d03ff2..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *  Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- *  Copyright (C) 2008 Collabora Ltd.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef GOwnPtr_h
-#define GOwnPtr_h
-
-#include <algorithm>
-#include <glib.h>
-#include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
-
-namespace WTF {
-    template <typename T> inline void freeOwnedGPtr(T* ptr) { g_free(reinterpret_cast<void*>(ptr)); }
-    template<> void freeOwnedGPtr<GError>(GError*);
-    template<> void freeOwnedGPtr<GList>(GList*);
-    template<> void freeOwnedGPtr<GCond>(GCond*);
-    template<> void freeOwnedGPtr<GMutex>(GMutex*);
-    template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*);
-    template<> void freeOwnedGPtr<GDir>(GDir*);
-    template<> void freeOwnedGPtr<GHashTable>(GHashTable*);
-
-    template <typename T> class GOwnPtr : Noncopyable {
-    public:
-        explicit GOwnPtr(T* ptr = 0) : m_ptr(ptr) { }
-        ~GOwnPtr() { freeOwnedGPtr(m_ptr); }
-
-        T* get() const { return m_ptr; }
-        T* release() { T* ptr = m_ptr; m_ptr = 0; return ptr; }
-        T*& outPtr() { ASSERT(!m_ptr); return m_ptr; }
-
-        void set(T* ptr) { ASSERT(!ptr || m_ptr != ptr); freeOwnedGPtr(m_ptr); m_ptr = ptr; }
-        void clear() { freeOwnedGPtr(m_ptr); m_ptr = 0; }
-
-        T& operator*() const { ASSERT(m_ptr); return *m_ptr; }
-        T* operator->() const { ASSERT(m_ptr); return m_ptr; }
-
-        bool operator!() const { return !m_ptr; }
-
-        // This conversion operator allows implicit conversion to bool but not to other integer types.
-        typedef T* GOwnPtr::*UnspecifiedBoolType;
-        operator UnspecifiedBoolType() const { return m_ptr ? &GOwnPtr::m_ptr : 0; }
-
-        void swap(GOwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
-
-    private:
-        T* m_ptr;
-    };
-    
-    template <typename T> inline void swap(GOwnPtr<T>& a, GOwnPtr<T>& b) { a.swap(b); }
-
-    template <typename T, typename U> inline bool operator==(const GOwnPtr<T>& a, U* b)
-    { 
-        return a.get() == b; 
-    }
-    
-    template <typename T, typename U> inline bool operator==(T* a, const GOwnPtr<U>& b) 
-    {
-        return a == b.get(); 
-    }
-
-    template <typename T, typename U> inline bool operator!=(const GOwnPtr<T>& a, U* b)
-    {
-        return a.get() != b; 
-    }
-
-    template <typename T, typename U> inline bool operator!=(T* a, const GOwnPtr<U>& b)
-    { 
-        return a != b.get(); 
-    }
-    
-    template <typename T> inline typename GOwnPtr<T>::PtrType getPtr(const GOwnPtr<T>& p)
-    {
-        return p.get();
-    }
-
-} // namespace WTF
-
-using WTF::GOwnPtr;
-
-#endif // GOwnPtr_h
index 1a422d8170ca982ca90836cf06bdf304c047f955..165eb41346b8b15de4e0e4c97826afcc1b6cc7c9 100644 (file)
@@ -49,23 +49,28 @@ namespace WTF {
         const_iterator begin() const;
         const_iterator end() const;
         
         const_iterator begin() const;
         const_iterator end() const;
         
-        iterator find(const ValueType& value);
-        const_iterator find(const ValueType& value) const;
-        bool contains(const ValueType& value) const;
-        unsigned count(const ValueType& value) const;
+        iterator find(const ValueType&);
+        const_iterator find(const ValueType&) const;
+        bool contains(const ValueType&) const;
+        unsigned count(const ValueType&) const;
 
         // increases the count if an equal value is already present
         // the return value is a pair of an interator to the new value's location, 
         // and a bool that is true if an new entry was added
 
         // increases the count if an equal value is already present
         // the return value is a pair of an interator to the new value's location, 
         // and a bool that is true if an new entry was added
-        std::pair<iterator, bool> add(const ValueType &value);
+        std::pair<iterator, bool> add(const ValueType&);
         
         // reduces the count of the value, and removes it if count
         // goes down to zero
         
         // reduces the count of the value, and removes it if count
         // goes down to zero
-        void remove(const ValueType& value);
-        void remove(iterator it);
+        void remove(const ValueType&);
+        void remove(iterator);
  
  
-       void clear();
-        
+        // removes the value, regardless of its count
+        void removeAll(iterator);
+        void removeAll(const ValueType&);
+
+        // clears the whole set
+        void clear();
+
     private:
         ImplType m_impl;
     };
     private:
         ImplType m_impl;
     };
@@ -165,6 +170,21 @@ namespace WTF {
             it->second = newVal;
     }
     
             it->second = newVal;
     }
     
+    template<typename Value, typename HashFunctions, typename Traits>
+    inline void HashCountedSet<Value, HashFunctions, Traits>::removeAll(const ValueType& value)
+    {
+        removeAll(find(value));
+    }
+    
+    template<typename Value, typename HashFunctions, typename Traits>
+    inline void HashCountedSet<Value, HashFunctions, Traits>::removeAll(iterator it)
+    {
+        if (it == end())
+            return;
+
+        m_impl.remove(it);
+    }
+    
     template<typename Value, typename HashFunctions, typename Traits>
     inline void HashCountedSet<Value, HashFunctions, Traits>::clear()
     {
     template<typename Value, typename HashFunctions, typename Traits>
     inline void HashCountedSet<Value, HashFunctions, Traits>::clear()
     {
index 13afb723df67eb595cfbd2a844ff4a52cebb5c74..2c66a2d9fbf3ce0f7719368f57cbb1557b01fc78 100644 (file)
@@ -173,9 +173,6 @@ namespace WTF {
     template<typename P> struct DefaultHash<RefPtr<P> > { typedef PtrHash<RefPtr<P> > Hash; };
 
     template<typename T, typename U> struct DefaultHash<std::pair<T, U> > { typedef PairHash<T, U> Hash; };
     template<typename P> struct DefaultHash<RefPtr<P> > { typedef PtrHash<RefPtr<P> > Hash; };
 
     template<typename T, typename U> struct DefaultHash<std::pair<T, U> > { typedef PairHash<T, U> Hash; };
-    
-    // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
-    static const unsigned stringHashingStartValue = 0x9e3779b9U;
 
 } // namespace WTF
 
 
 } // namespace WTF
 
index 3de5ee6e0cb02017a0f146a14ba9bf8f30075c16..d63a8d4560f212bc00915d99a54a6049c21cca39 100644 (file)
@@ -83,6 +83,25 @@ namespace WTF {
 
         MappedType take(const KeyType&); // efficient combination of get with remove
 
 
         MappedType take(const KeyType&); // efficient combination of get with remove
 
+        // An alternate version of find() that finds the object by hashing and comparing
+        // with some other type, to avoid the cost of type conversion. HashTranslator
+        // must have the following function members:
+        //   static unsigned hash(const T&);
+        //   static bool equal(const ValueType&, const T&);
+        template<typename T, typename HashTranslator> iterator find(const T&);
+        template<typename T, typename HashTranslator> const_iterator find(const T&) const;
+        template<typename T, typename HashTranslator> bool contains(const T&) const;
+
+        // An alternate version of add() that finds the object by hashing and comparing
+        // with some other type, to avoid the cost of type conversion if the object is already
+        // in the table. HashTranslator must have the following function members:
+        //   static unsigned hash(const T&);
+        //   static bool equal(const ValueType&, const T&);
+        //   static translate(ValueType&, const T&, unsigned hashCode);
+        template<typename T, typename HashTranslator> pair<iterator, bool> add(const T&, const MappedType&);
+
+        void checkConsistency() const;
+
     private:
         pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
 
     private:
         pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
 
@@ -107,6 +126,19 @@ namespace WTF {
         }
     };
 
         }
     };
 
+    template<typename ValueType, typename ValueTraits, typename T, typename Translator>
+    struct HashMapTranslatorAdapter {
+        typedef typename ValueType::first_type KeyType;
+        typedef typename ValueType::second_type MappedType;
+
+        static unsigned hash(const T& key) { return Translator::hash(key); }
+        static bool equal(const KeyType& a, const T& b) { return Translator::equal(a, b); }
+        static void translate(ValueType& location, const T& key, const MappedType&, unsigned hashCode)
+        {
+            Translator::translate(location.first, key, hashCode);
+        }
+    };
+
     template<typename T, typename U, typename V, typename W, typename X>
     inline void HashMap<T, U, V, W, X>::swap(HashMap& other)
     {
     template<typename T, typename U, typename V, typename W, typename X>
     inline void HashMap<T, U, V, W, X>::swap(HashMap& other)
     {
@@ -173,6 +205,33 @@ namespace WTF {
         return m_impl.contains(key);
     }
 
         return m_impl.contains(key);
     }
 
+    template<typename T, typename U, typename V, typename W, typename X>
+    template<typename TYPE, typename HashTranslator>
+    inline typename HashMap<T, U, V, W, X>::iterator
+    HashMap<T, U, V, W, X>::find(const TYPE& value)
+    {
+        typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter;
+        return m_impl.template find<TYPE, Adapter>(value);
+    }
+
+    template<typename T, typename U, typename V, typename W, typename X>
+    template<typename TYPE, typename HashTranslator>
+    inline typename HashMap<T, U, V, W, X>::const_iterator 
+    HashMap<T, U, V, W, X>::find(const TYPE& value) const
+    {
+        typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter;
+        return m_impl.template find<TYPE, Adapter>(value);
+    }
+
+    template<typename T, typename U, typename V, typename W, typename X>
+    template<typename TYPE, typename HashTranslator>
+    inline bool
+    HashMap<T, U, V, W, X>::contains(const TYPE& value) const
+    {
+        typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter;
+        return m_impl.template contains<TYPE, Adapter>(value);
+    }
+
     template<typename T, typename U, typename V, typename W, typename X>
     inline pair<typename HashMap<T, U, V, W, X>::iterator, bool>
     HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped) 
     template<typename T, typename U, typename V, typename W, typename X>
     inline pair<typename HashMap<T, U, V, W, X>::iterator, bool>
     HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped) 
@@ -193,6 +252,15 @@ namespace WTF {
         return result;
     }
 
         return result;
     }
 
+    template<typename T, typename U, typename V, typename W, typename X>
+    template<typename TYPE, typename HashTranslator>
+    pair<typename HashMap<T, U, V, W, X>::iterator, bool>
+    HashMap<T, U, V, W, X>::add(const TYPE& key, const MappedType& value)
+    {
+        typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter;
+        return m_impl.template addPassingHashCode<TYPE, MappedType, Adapter>(key, value);
+    }
+
     template<typename T, typename U, typename V, typename W, typename X>
     pair<typename HashMap<T, U, V, W, X>::iterator, bool>
     HashMap<T, U, V, W, X>::add(const KeyType& key, const MappedType& mapped)
     template<typename T, typename U, typename V, typename W, typename X>
     pair<typename HashMap<T, U, V, W, X>::iterator, bool>
     HashMap<T, U, V, W, X>::add(const KeyType& key, const MappedType& mapped)
@@ -215,7 +283,7 @@ namespace WTF {
     {
         if (it.m_impl == m_impl.end())
             return;
     {
         if (it.m_impl == m_impl.end())
             return;
-        m_impl.checkTableConsistency();
+        m_impl.internalCheckTableConsistency();
         m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
     }
 
         m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
     }
 
@@ -244,6 +312,13 @@ namespace WTF {
         return result;
     }
 
         return result;
     }
 
+    template<typename T, typename U, typename V, typename W, typename X>
+    inline void HashMap<T, U, V, W, X>::checkConsistency() const
+    {
+        m_impl.checkTableConsistency();
+    }
+
+
     template<typename T, typename U, typename V, typename W, typename X>
     bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
     {
     template<typename T, typename U, typename V, typename W, typename X>
     bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
     {
index d664c67cf0ccaeb39f0e128e5be13f8e699f4b48..442949081f20d640c56639ca54876ab170899840 100644 (file)
@@ -29,6 +29,8 @@ namespace WTF {
     template<typename Value, typename HashFunctions, typename Traits> class HashSet;
     template<typename Value, typename HashFunctions, typename Traits>
     void deleteAllValues(const HashSet<Value, HashFunctions, Traits>&);
     template<typename Value, typename HashFunctions, typename Traits> class HashSet;
     template<typename Value, typename HashFunctions, typename Traits>
     void deleteAllValues(const HashSet<Value, HashFunctions, Traits>&);
+    template<typename Value, typename HashFunctions, typename Traits>
+    void fastDeleteAllValues(const HashSet<Value, HashFunctions, Traits>&);
 
     template<typename T> struct IdentityExtractor;
 
 
     template<typename T> struct IdentityExtractor;
 
@@ -79,7 +81,7 @@ namespace WTF {
 
         // An alternate version of add() that finds the object by hashing and comparing
         // with some other type, to avoid the cost of type conversion if the object is already
 
         // An alternate version of add() that finds the object by hashing and comparing
         // with some other type, to avoid the cost of type conversion if the object is already
-        // in the table. HashTranslator must have the following methods:
+        // in the table. HashTranslator must have the following function members:
         //   static unsigned hash(const T&);
         //   static bool equal(const ValueType&, const T&);
         //   static translate(ValueType&, const T&, unsigned hashCode);
         //   static unsigned hash(const T&);
         //   static bool equal(const ValueType&, const T&);
         //   static translate(ValueType&, const T&, unsigned hashCode);
@@ -91,6 +93,7 @@ namespace WTF {
 
     private:
         friend void deleteAllValues<>(const HashSet&);
 
     private:
         friend void deleteAllValues<>(const HashSet&);
+        friend void fastDeleteAllValues<>(const HashSet&);
 
         HashTableType m_impl;
     };
 
         HashTableType m_impl;
     };
@@ -176,28 +179,28 @@ namespace WTF {
     }
 
     template<typename Value, typename HashFunctions, typename Traits>
     }
 
     template<typename Value, typename HashFunctions, typename Traits>
-    template<typename T, typename Translator> 
+    template<typename T, typename HashTranslator>
     typename HashSet<Value, HashFunctions, Traits>::iterator
     inline HashSet<Value, HashFunctions, Traits>::find(const T& value)
     {
     typename HashSet<Value, HashFunctions, Traits>::iterator
     inline HashSet<Value, HashFunctions, Traits>::find(const T& value)
     {
-        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
+        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, HashTranslator> Adapter;
         return m_impl.template find<T, Adapter>(value);
     }
 
     template<typename Value, typename HashFunctions, typename Traits>
         return m_impl.template find<T, Adapter>(value);
     }
 
     template<typename Value, typename HashFunctions, typename Traits>
-    template<typename T, typename Translator> 
+    template<typename T, typename HashTranslator>
     typename HashSet<Value, HashFunctions, Traits>::const_iterator
     inline HashSet<Value, HashFunctions, Traits>::find(const T& value) const
     {
     typename HashSet<Value, HashFunctions, Traits>::const_iterator
     inline HashSet<Value, HashFunctions, Traits>::find(const T& value) const
     {
-        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
+        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, HashTranslator> Adapter;
         return m_impl.template find<T, Adapter>(value);
     }
 
     template<typename Value, typename HashFunctions, typename Traits>
         return m_impl.template find<T, Adapter>(value);
     }
 
     template<typename Value, typename HashFunctions, typename Traits>
-    template<typename T, typename Translator> 
+    template<typename T, typename HashTranslator>
     inline bool HashSet<Value, HashFunctions, Traits>::contains(const T& value) const
     {
     inline bool HashSet<Value, HashFunctions, Traits>::contains(const T& value) const
     {
-        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
+        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, HashTranslator> Adapter;
         return m_impl.template contains<T, Adapter>(value);
     }
 
         return m_impl.template contains<T, Adapter>(value);
     }
 
@@ -208,11 +211,11 @@ namespace WTF {
     }
 
     template<typename Value, typename HashFunctions, typename Traits>
     }
 
     template<typename Value, typename HashFunctions, typename Traits>
-    template<typename T, typename Translator> 
+    template<typename T, typename HashTranslator>
     pair<typename HashSet<Value, HashFunctions, Traits>::iterator, bool>
     HashSet<Value, HashFunctions, Traits>::add(const T& value)
     {
     pair<typename HashSet<Value, HashFunctions, Traits>::iterator, bool>
     HashSet<Value, HashFunctions, Traits>::add(const T& value)
     {
-        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, Translator> Adapter;
+        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, HashTranslator> Adapter;
         return m_impl.template addPassingHashCode<T, T, Adapter>(value, value);
     }
 
         return m_impl.template addPassingHashCode<T, T, Adapter>(value, value);
     }
 
@@ -221,7 +224,7 @@ namespace WTF {
     {
         if (it.m_impl == m_impl.end())
             return;
     {
         if (it.m_impl == m_impl.end())
             return;
-        m_impl.checkTableConsistency();
+        m_impl.internalCheckTableConsistency();
         m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
     }
 
         m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
     }
 
@@ -251,6 +254,21 @@ namespace WTF {
     {
         deleteAllValues<typename HashSet<T, U, V>::ValueType>(collection.m_impl);
     }
     {
         deleteAllValues<typename HashSet<T, U, V>::ValueType>(collection.m_impl);
     }
+
+    template<typename ValueType, typename HashTableType>
+    void fastDeleteAllValues(HashTableType& collection)
+    {
+        typedef typename HashTableType::const_iterator iterator;
+        iterator end = collection.end();
+        for (iterator it = collection.begin(); it != end; ++it)
+            fastDelete(*it);
+    }
+
+    template<typename T, typename U, typename V>
+    inline void fastDeleteAllValues(const HashSet<T, U, V>& collection)
+    {
+        fastDeleteAllValues<typename HashSet<T, U, V>::ValueType>(collection.m_impl);
+    }
     
     template<typename T, typename U, typename V, typename W>
     inline void copyToVector(const HashSet<T, U, V>& collection, W& vector)
     
     template<typename T, typename U, typename V, typename W>
     inline void copyToVector(const HashSet<T, U, V>& collection, W& vector)
index 3b283f82282efb3728e092feaa2379e20985dea0..ceb89636368ea20ef522914b4c3d0a910205f58d 100644 (file)
 
 #include "FastMalloc.h"
 #include "HashTraits.h"
 
 #include "FastMalloc.h"
 #include "HashTraits.h"
+#include "ValueCheck.h"
 #include <wtf/Assertions.h>
 #include <wtf/Threading.h>
 
 namespace WTF {
 
 #define DUMP_HASHTABLE_STATS 0
 #include <wtf/Assertions.h>
 #include <wtf/Threading.h>
 
 namespace WTF {
 
 #define DUMP_HASHTABLE_STATS 0
+// Enables internal WTF consistency checks that are invoked automatically. Non-WTF callers can call checkTableConsistency() even if internal checks are disabled.
 #define CHECK_HASHTABLE_CONSISTENCY 0
 
 #ifdef NDEBUG
 #define CHECK_HASHTABLE_CONSISTENCY 0
 
 #ifdef NDEBUG
@@ -197,7 +199,7 @@ namespace WTF {
         void checkValidity(const const_iterator& other) const
         {
             ASSERT(m_table);
         void checkValidity(const const_iterator& other) const
         {
             ASSERT(m_table);
-            ASSERT(other.m_table);
+            ASSERT_UNUSED(other, other.m_table);
             ASSERT(m_table == other.m_table);
         }
 #else
             ASSERT(m_table == other.m_table);
         }
 #else
@@ -340,11 +342,18 @@ namespace WTF {
         ValueType* lookup(const Key& key) { return lookup<Key, IdentityTranslatorType>(key); }
         template<typename T, typename HashTranslator> ValueType* lookup(const T&);
 
         ValueType* lookup(const Key& key) { return lookup<Key, IdentityTranslatorType>(key); }
         template<typename T, typename HashTranslator> ValueType* lookup(const T&);
 
-#if CHECK_HASHTABLE_CONSISTENCY
+#if !ASSERT_DISABLED
         void checkTableConsistency() const;
 #else
         static void checkTableConsistency() { }
 #endif
         void checkTableConsistency() const;
 #else
         static void checkTableConsistency() { }
 #endif
+#if CHECK_HASHTABLE_CONSISTENCY
+        void internalCheckTableConsistency() const { checkTableConsistency(); }
+        void internalCheckTableConsistencyExceptSize() const { checkTableConsistencyExceptSize(); }
+#else
+        static void internalCheckTableConsistencyExceptSize() { }
+        static void internalCheckTableConsistency() { }
+#endif
 
     private:
         static ValueType* allocateTable(int size);
 
     private:
         static ValueType* allocateTable(int size);
@@ -383,7 +392,7 @@ namespace WTF {
         iterator makeKnownGoodIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); }
         const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); }
 
         iterator makeKnownGoodIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); }
         const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); }
 
-#if CHECK_HASHTABLE_CONSISTENCY
+#if !ASSERT_DISABLED
         void checkTableConsistencyExceptSize() const;
 #else
         static void checkTableConsistencyExceptSize() { }
         void checkTableConsistencyExceptSize() const;
 #else
         static void checkTableConsistencyExceptSize() { }
@@ -624,7 +633,7 @@ namespace WTF {
         if (!m_table)
             expand();
 
         if (!m_table)
             expand();
 
-        checkTableConsistency();
+        internalCheckTableConsistency();
 
         ASSERT(m_table);
 
 
         ASSERT(m_table);
 
@@ -693,7 +702,7 @@ namespace WTF {
             return p;
         }
         
             return p;
         }
         
-        checkTableConsistency();
+        internalCheckTableConsistency();
         
         return std::make_pair(makeKnownGoodIterator(entry), true);
     }
         
         return std::make_pair(makeKnownGoodIterator(entry), true);
     }
@@ -709,7 +718,7 @@ namespace WTF {
         if (!m_table)
             expand();
 
         if (!m_table)
             expand();
 
-        checkTableConsistency();
+        internalCheckTableConsistency();
 
         FullLookupType lookupResult = fullLookupForWriting<T, HashTranslator>(key);
 
 
         FullLookupType lookupResult = fullLookupForWriting<T, HashTranslator>(key);
 
@@ -738,7 +747,7 @@ namespace WTF {
             return p;
         }
 
             return p;
         }
 
-        checkTableConsistency();
+        internalCheckTableConsistency();
 
         return std::make_pair(makeKnownGoodIterator(entry), true);
     }
 
         return std::make_pair(makeKnownGoodIterator(entry), true);
     }
@@ -805,7 +814,7 @@ namespace WTF {
     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeAndInvalidate(ValueType* pos)
     {
         invalidateIterators();
     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeAndInvalidate(ValueType* pos)
     {
         invalidateIterators();
-        checkTableConsistency();
+        internalCheckTableConsistency();
         remove(pos);
     }
 
         remove(pos);
     }
 
@@ -823,7 +832,7 @@ namespace WTF {
         if (shouldShrink())
             shrink();
 
         if (shouldShrink())
             shrink();
 
-        checkTableConsistency();
+        internalCheckTableConsistency();
     }
 
     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
     }
 
     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
@@ -892,7 +901,7 @@ namespace WTF {
     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::rehash(int newTableSize)
     {
     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::rehash(int newTableSize)
     {
-        checkTableConsistencyExceptSize();
+        internalCheckTableConsistencyExceptSize();
 
         int oldTableSize = m_tableSize;
         ValueType* oldTable = m_table;
 
         int oldTableSize = m_tableSize;
         ValueType* oldTable = m_table;
@@ -914,7 +923,7 @@ namespace WTF {
 
         deallocateTable(oldTable, oldTableSize);
 
 
         deallocateTable(oldTable, oldTableSize);
 
-        checkTableConsistency();
+        internalCheckTableConsistency();
     }
 
     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
     }
 
     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
@@ -981,13 +990,13 @@ namespace WTF {
         return *this;
     }
 
         return *this;
     }
 
-#if CHECK_HASHTABLE_CONSISTENCY
+#if !ASSERT_DISABLED
 
     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkTableConsistency() const
     {
         checkTableConsistencyExceptSize();
 
     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
     void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkTableConsistency() const
     {
         checkTableConsistencyExceptSize();
-        ASSERT(!shouldExpand());
+        ASSERT(!m_table || !shouldExpand());
         ASSERT(!shouldShrink());
     }
 
         ASSERT(!shouldShrink());
     }
 
@@ -1012,6 +1021,8 @@ namespace WTF {
             const_iterator it = find(Extractor::extract(*entry));
             ASSERT(entry == it.m_position);
             ++count;
             const_iterator it = find(Extractor::extract(*entry));
             ASSERT(entry == it.m_position);
             ++count;
+
+            ValueCheck<Key>::checkConsistency(it->first);
         }
 
         ASSERT(count == m_keyCount);
         }
 
         ASSERT(count == m_keyCount);
@@ -1021,7 +1032,7 @@ namespace WTF {
         ASSERT(m_tableSize == m_tableSizeMask + 1);
     }
 
         ASSERT(m_tableSize == m_tableSizeMask + 1);
     }
 
-#endif // CHECK_HASHTABLE_CONSISTENCY
+#endif // ASSERT_DISABLED
 
 #if CHECK_HASHTABLE_ITERATORS
 
 
 #if CHECK_HASHTABLE_ITERATORS
 
index 38cc99850653100f2e53e3f3dd58c19eb1e8558f..54ed36b2a9639fcd53999edcb051af9c95030a27 100644 (file)
@@ -51,7 +51,7 @@ namespace WTF {
     template<typename ValueArg> struct ListHashSetNodeAllocator;
     template<typename ValueArg, typename HashArg> struct ListHashSetNodeHashFunctions;
 
     template<typename ValueArg> struct ListHashSetNodeAllocator;
     template<typename ValueArg, typename HashArg> struct ListHashSetNodeHashFunctions;
 
-    template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet {
+    template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet : public FastAllocBase {
     private:
         typedef ListHashSetNode<ValueArg> Node;
         typedef ListHashSetNodeAllocator<ValueArg> NodeAllocator;
     private:
         typedef ListHashSetNode<ValueArg> Node;
         typedef ListHashSetNodeAllocator<ValueArg> NodeAllocator;
index 9f9a354a38e7a2c5a8233255cb0898634cefb66d..8bf6447446b8fb989515eb2cf3b79b19f8ae092a 100644 (file)
@@ -34,13 +34,8 @@ namespace WTF {
         ListRefPtr(const RefPtr<T>& o) : RefPtr<T>(o) {}
         // see comment in PassRefPtr.h for why this takes const reference
         template <typename U> ListRefPtr(const PassRefPtr<U>& o) : RefPtr<T>(o) {}
         ListRefPtr(const RefPtr<T>& o) : RefPtr<T>(o) {}
         // see comment in PassRefPtr.h for why this takes const reference
         template <typename U> ListRefPtr(const PassRefPtr<U>& o) : RefPtr<T>(o) {}
-
-        ~ListRefPtr()
-        {
-            RefPtr<T> reaper = this->release();
-            while (reaper && reaper->hasOneRef())
-                reaper = reaper->releaseNext(); // implicitly protects reaper->next, then derefs reaper
-        }
+        
+        ~ListRefPtr();
         
         ListRefPtr& operator=(T* optr) { RefPtr<T>::operator=(optr); return *this; }
         ListRefPtr& operator=(const RefPtr<T>& o) { RefPtr<T>::operator=(o); return *this; }
         
         ListRefPtr& operator=(T* optr) { RefPtr<T>::operator=(optr); return *this; }
         ListRefPtr& operator=(const RefPtr<T>& o) { RefPtr<T>::operator=(o); return *this; }
@@ -49,6 +44,20 @@ namespace WTF {
         template <typename U> ListRefPtr& operator=(const PassRefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; }
     };
 
         template <typename U> ListRefPtr& operator=(const PassRefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; }
     };
 
+    // Remove inline for winscw compiler to prevent the compiler agressively resolving
+    // T::ref() in RefPtr<T>'s copy constructor.  The bug is reported at:
+    // https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=9812.
+    template <typename T> 
+#if !COMPILER(WINSCW)
+    inline
+#endif
+    ListRefPtr<T>::~ListRefPtr()
+    {
+        RefPtr<T> reaper = this->release();
+        while (reaper && reaper->hasOneRef())
+            reaper = reaper->releaseNext(); // implicitly protects reaper->next, then derefs reaper
+    }
+
     template <typename T> inline T* getPtr(const ListRefPtr<T>& p)
     {
         return p.get();
     template <typename T> inline T* getPtr(const ListRefPtr<T>& p)
     {
         return p.get();
index 9feec1f3f7e79aa11349b64ed4f43316716878a2..41813d3f9f49a9c892c02992b0393b4333c04057 100644 (file)
@@ -32,7 +32,7 @@
 
 namespace WTF {
 
 
 namespace WTF {
 
-template <typename T> class Locker : Noncopyable {
+template <typename T> class Locker : public Noncopyable {
 public:
     Locker(T& lockable) : m_lockable(lockable) { m_lockable.lock(); }
     ~Locker() { m_lockable.unlock(); }
 public:
     Locker(T& lockable) : m_lockable(lockable) { m_lockable.lock(); }
     ~Locker() { m_lockable.unlock(); }
index e999094df21daba1b533d3c161edbef61ccc95c0..40a4ae530818ea30d973afce7127f6e2000f7d91 100644 (file)
@@ -39,10 +39,12 @@ namespace WTF {
 struct FunctionWithContext {
     MainThreadFunction* function;
     void* context;
 struct FunctionWithContext {
     MainThreadFunction* function;
     void* context;
+    ThreadCondition* syncFlag;
 
 
-    FunctionWithContext(MainThreadFunction* function = 0, void* context = 0)
+    FunctionWithContext(MainThreadFunction* function = 0, void* context = 0, ThreadCondition* syncFlag = 0)
         : function(function)
         , context(context)
         : function(function)
         , context(context)
+        , syncFlag(syncFlag)
     { 
     }
 };
     { 
     }
 };
@@ -92,6 +94,8 @@ void dispatchFunctionsFromMainThread()
         }
 
         invocation.function(invocation.context);
         }
 
         invocation.function(invocation.context);
+        if (invocation.syncFlag)
+            invocation.syncFlag->signal();
 
         // If we are running accumulated functions for too long so UI may become unresponsive, we need to
         // yield so the user input can be processed. Otherwise user may not be able to even close the window.
 
         // If we are running accumulated functions for too long so UI may become unresponsive, we need to
         // yield so the user input can be processed. Otherwise user may not be able to even close the window.
@@ -117,6 +121,24 @@ void callOnMainThread(MainThreadFunction* function, void* context)
         scheduleDispatchFunctionsOnMainThread();
 }
 
         scheduleDispatchFunctionsOnMainThread();
 }
 
+void callOnMainThreadAndWait(MainThreadFunction* function, void* context)
+{
+    ASSERT(function);
+
+    if (isMainThread()) {
+        function(context);
+        return;
+    }
+
+    ThreadCondition syncFlag;
+    Mutex& functionQueueMutex = mainThreadFunctionQueueMutex();
+    MutexLocker locker(functionQueueMutex);
+    functionQueue().append(FunctionWithContext(function, context, &syncFlag));
+    if (functionQueue().size() == 1)
+        scheduleDispatchFunctionsOnMainThread();
+    syncFlag.wait(functionQueueMutex);
+}
+
 void setMainThreadCallbacksPaused(bool paused)
 {
     ASSERT(isMainThread());
 void setMainThreadCallbacksPaused(bool paused)
 {
     ASSERT(isMainThread());
index 01ce80476fde8e6816e54878b262407341fe4c96..8c0275bac6377779f5fbe88d3c4e3dc8684946af 100644 (file)
@@ -38,6 +38,9 @@ typedef void MainThreadFunction(void*);
 
 void callOnMainThread(MainThreadFunction*, void* context);
 
 
 void callOnMainThread(MainThreadFunction*, void* context);
 
+// Blocks the thread until the call finishes on the main thread. Misusing this can easily cause deadlocks.
+void callOnMainThreadAndWait(MainThreadFunction*, void* context);
+
 void setMainThreadCallbacksPaused(bool paused);
 
 // Must be called from the main thread (Darwin is an exception to this rule).
 void setMainThreadCallbacksPaused(bool paused);
 
 // Must be called from the main thread (Darwin is an exception to this rule).
@@ -52,6 +55,7 @@ void dispatchFunctionsFromMainThread();
 } // namespace WTF
 
 using WTF::callOnMainThread;
 } // namespace WTF
 
 using WTF::callOnMainThread;
+using WTF::callOnMainThreadAndWait;
 using WTF::setMainThreadCallbacksPaused;
 
 #endif // MainThread_h
 using WTF::setMainThreadCallbacksPaused;
 
 #endif // MainThread_h
index 324300d3a14176a55f0eeac1cd3dba94dff039ce..9ea57fd771b54585ba3ef98ca530559936e21c5b 100644 (file)
 #ifndef WTF_MathExtras_h
 #define WTF_MathExtras_h
 
 #ifndef WTF_MathExtras_h
 #define WTF_MathExtras_h
 
+#include <float.h>
 #include <math.h>
 #include <stdlib.h>
 
 #include <math.h>
 #include <stdlib.h>
 
-#if PLATFORM(SOLARIS)
+#if OS(SOLARIS)
 #include <ieeefp.h>
 #endif
 
 #include <ieeefp.h>
 #endif
 
-#if PLATFORM(OPENBSD)
+#if OS(OPENBSD)
 #include <sys/types.h>
 #include <machine/ieee.h>
 #endif
 
 #if COMPILER(MSVC)
 #include <sys/types.h>
 #include <machine/ieee.h>
 #endif
 
 #if COMPILER(MSVC)
-#if PLATFORM(WINCE)
+#if OS(WINCE)
 #include <stdlib.h>
 #endif
 #include <limits>
 #include <stdlib.h>
 #endif
 #include <limits>
-
-#if HAVE(FLOAT_H)
-#include <float.h>
-#endif
-
 #endif
 
 #ifndef M_PI
 #endif
 
 #ifndef M_PI
@@ -66,7 +62,7 @@ const double piOverFourDouble = M_PI_4;
 const float piOverFourFloat = static_cast<float>(M_PI_4);
 #endif
 
 const float piOverFourFloat = static_cast<float>(M_PI_4);
 #endif
 
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
 
 // Work around a bug in the Mac OS X libc where ceil(-0.1) return +0.
 inline double wtf_ceil(double x) { return copysign(ceil(x), x); }
 
 // Work around a bug in the Mac OS X libc where ceil(-0.1) return +0.
 inline double wtf_ceil(double x) { return copysign(ceil(x), x); }
@@ -75,7 +71,7 @@ inline double wtf_ceil(double x) { return copysign(ceil(x), x); }
 
 #endif
 
 
 #endif
 
-#if PLATFORM(SOLARIS)
+#if OS(SOLARIS)
 
 #ifndef isfinite
 inline bool isfinite(double x) { return finite(x) && !isnand(x); }
 
 #ifndef isfinite
 inline bool isfinite(double x) { return finite(x) && !isnand(x); }
@@ -89,7 +85,7 @@ inline bool signbit(double x) { return x < 0.0; } // FIXME: Wrong for negative 0
 
 #endif
 
 
 #endif
 
-#if PLATFORM(OPENBSD)
+#if OS(OPENBSD)
 
 #ifndef isfinite
 inline bool isfinite(double x) { return finite(x); }
 
 #ifndef isfinite
 inline bool isfinite(double x) { return finite(x); }
@@ -102,6 +98,8 @@ inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x
 
 #if COMPILER(MSVC) || COMPILER(RVCT)
 
 
 #if COMPILER(MSVC) || COMPILER(RVCT)
 
+inline long long llround(double num) { return static_cast<long long>(num > 0 ? num + 0.5 : ceil(num - 0.5)); }
+inline long long llroundf(float num) { return static_cast<long long>(num > 0 ? num + 0.5f : ceil(num - 0.5f)); }
 inline long lround(double num) { return static_cast<long>(num > 0 ? num + 0.5 : ceil(num - 0.5)); }
 inline long lroundf(float num) { return static_cast<long>(num > 0 ? num + 0.5f : ceilf(num - 0.5f)); }
 inline double round(double num) { return num > 0 ? floor(num + 0.5) : ceil(num - 0.5); }
 inline long lround(double num) { return static_cast<long>(num > 0 ? num + 0.5 : ceil(num - 0.5)); }
 inline long lroundf(float num) { return static_cast<long>(num > 0 ? num + 0.5f : ceilf(num - 0.5f)); }
 inline double round(double num) { return num > 0 ? floor(num + 0.5) : ceil(num - 0.5); }
index 7721dba512187e7c05a2ba18aa3e57e2f32cdfb8..48bd10ad0dca9b18d819307027923ce06df6880f 100644 (file)
@@ -44,20 +44,28 @@ namespace WTF {
         MessageQueueMessageReceived,  // A message was successfully received and returned.
     };
 
         MessageQueueMessageReceived,  // A message was successfully received and returned.
     };
 
+    // The queue takes ownership of messages and transfer it to the new owner
+    // when messages are fetched from the queue.
+    // Essentially, MessageQueue acts as a queue of OwnPtr<DataType>.
     template<typename DataType>
     template<typename DataType>
-    class MessageQueue : Noncopyable {
+    class MessageQueue : public Noncopyable {
     public:
         MessageQueue() : m_killed(false) { }
     public:
         MessageQueue() : m_killed(false) { }
-        
-        void append(const DataType&);
-        bool appendAndCheckEmpty(const DataType&);
-        void prepend(const DataType&);
-        bool waitForMessage(DataType&);
+        ~MessageQueue();
+
+        void append(PassOwnPtr<DataType>);
+        bool appendAndCheckEmpty(PassOwnPtr<DataType>);
+        void prepend(PassOwnPtr<DataType>);
+
+        PassOwnPtr<DataType> waitForMessage();
+        PassOwnPtr<DataType> tryGetMessage();
         template<typename Predicate>
         template<typename Predicate>
-        MessageQueueWaitResult waitForMessageFilteredWithTimeout(DataType&, Predicate&, double absoluteTime);
-        void kill();
+        PassOwnPtr<DataType> waitForMessageFilteredWithTimeout(MessageQueueWaitResult&, Predicate&, double absoluteTime);
+
+        template<typename Predicate>
+        void removeIf(Predicate&);
 
 
-        bool tryGetMessage(DataType&);
+        void kill();
         bool killed() const;
 
         // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
         bool killed() const;
 
         // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
@@ -66,86 +74,115 @@ namespace WTF {
         static double infiniteTime() { return std::numeric_limits<double>::max(); }
 
     private:
         static double infiniteTime() { return std::numeric_limits<double>::max(); }
 
     private:
-        static bool alwaysTruePredicate(DataType&) { return true; }
+        static bool alwaysTruePredicate(DataType*) { return true; }
 
         mutable Mutex m_mutex;
         ThreadCondition m_condition;
 
         mutable Mutex m_mutex;
         ThreadCondition m_condition;
-        Deque<DataType> m_queue;
+        Deque<DataType*> m_queue;
         bool m_killed;
     };
 
     template<typename DataType>
         bool m_killed;
     };
 
     template<typename DataType>
-    inline void MessageQueue<DataType>::append(const DataType& message)
+    MessageQueue<DataType>::~MessageQueue()
+    {
+        deleteAllValues(m_queue);
+    }
+
+    template<typename DataType>
+    inline void MessageQueue<DataType>::append(PassOwnPtr<DataType> message)
     {
         MutexLocker lock(m_mutex);
     {
         MutexLocker lock(m_mutex);
-        m_queue.append(message);
+        m_queue.append(message.release());
         m_condition.signal();
     }
 
     // Returns true if the queue was empty before the item was added.
     template<typename DataType>
         m_condition.signal();
     }
 
     // Returns true if the queue was empty before the item was added.
     template<typename DataType>
-    inline bool MessageQueue<DataType>::appendAndCheckEmpty(const DataType& message)
+    inline bool MessageQueue<DataType>::appendAndCheckEmpty(PassOwnPtr<DataType> message)
     {
         MutexLocker lock(m_mutex);
         bool wasEmpty = m_queue.isEmpty();
     {
         MutexLocker lock(m_mutex);
         bool wasEmpty = m_queue.isEmpty();
-        m_queue.append(message);
+        m_queue.append(message.release());
         m_condition.signal();
         return wasEmpty;
     }
 
     template<typename DataType>
         m_condition.signal();
         return wasEmpty;
     }
 
     template<typename DataType>
-    inline void MessageQueue<DataType>::prepend(const DataType& message)
+    inline void MessageQueue<DataType>::prepend(PassOwnPtr<DataType> message)
     {
         MutexLocker lock(m_mutex);
     {
         MutexLocker lock(m_mutex);
-        m_queue.prepend(message);
+        m_queue.prepend(message.release());
         m_condition.signal();
     }
 
     template<typename DataType>
         m_condition.signal();
     }
 
     template<typename DataType>
-    inline bool MessageQueue<DataType>::waitForMessage(DataType& result)
+    inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessage()
     {
     {
-        MessageQueueWaitResult exitReason = waitForMessageFilteredWithTimeout(result, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime());
+        MessageQueueWaitResult exitReason; 
+        PassOwnPtr<DataType> result = waitForMessageFilteredWithTimeout(exitReason, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime());
         ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
         ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
-        return exitReason == MessageQueueMessageReceived;
+        return result;
     }
 
     template<typename DataType>
     template<typename Predicate>
     }
 
     template<typename DataType>
     template<typename Predicate>
-    inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageFilteredWithTimeout(DataType& result, Predicate& predicate, double absoluteTime)
+    inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessageFilteredWithTimeout(MessageQueueWaitResult& result, Predicate& predicate, double absoluteTime)
     {
         MutexLocker lock(m_mutex);
         bool timedOut = false;
 
     {
         MutexLocker lock(m_mutex);
         bool timedOut = false;
 
-        DequeConstIterator<DataType> found = m_queue.end();
+        DequeConstIterator<DataType*> found = m_queue.end();
         while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end())
             timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
 
         ASSERT(!timedOut || absoluteTime != infiniteTime());
 
         while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end())
             timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
 
         ASSERT(!timedOut || absoluteTime != infiniteTime());
 
-        if (m_killed)
-            return MessageQueueTerminated;
+        if (m_killed) {
+            result = MessageQueueTerminated;
+            return 0;
+        }
 
 
-        if (timedOut)
-            return MessageQueueTimeout;
+        if (timedOut) {
+            result = MessageQueueTimeout;
+            return 0;
+        }
 
         ASSERT(found != m_queue.end());
 
         ASSERT(found != m_queue.end());
-        result = *found;
+        DataType* message = *found;
         m_queue.remove(found);
         m_queue.remove(found);
-        return MessageQueueMessageReceived;
+        result = MessageQueueMessageReceived;
+        return message;
     }
 
     template<typename DataType>
     }
 
     template<typename DataType>
-    inline bool MessageQueue<DataType>::tryGetMessage(DataType& result)
+    inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessage()
     {
         MutexLocker lock(m_mutex);
         if (m_killed)
     {
         MutexLocker lock(m_mutex);
         if (m_killed)
-            return false;
+            return 0;
         if (m_queue.isEmpty())
         if (m_queue.isEmpty())
-            return false;
+            return 0;
 
 
-        result = m_queue.first();
+        DataType* message = m_queue.first();
         m_queue.removeFirst();
         m_queue.removeFirst();
-        return true;
+        return message;
+    }
+
+    template<typename DataType>
+    template<typename Predicate>
+    inline void MessageQueue<DataType>::removeIf(Predicate& predicate)
+    {
+        MutexLocker lock(m_mutex);
+        // See bug 31657 for why this loop looks so weird
+        while (true) {
+            DequeConstIterator<DataType*> found = m_queue.findIf(predicate);
+            if (found == m_queue.end())
+                break;
+
+            DataType* message = *found;
+            m_queue.remove(found);
+            delete message;
+       }
     }
 
     template<typename DataType>
     }
 
     template<typename DataType>
index f241c7c989ac62a77834b7ec1f9dc052215018f6..60a46e2669787bb02b7ee345d6cdef07a4c59de7 100644 (file)
 // We don't want argument-dependent lookup to pull in everything from the WTF
 // namespace when you use Noncopyable, so put it in its own namespace.
 
 // We don't want argument-dependent lookup to pull in everything from the WTF
 // namespace when you use Noncopyable, so put it in its own namespace.
 
+#include "FastAllocBase.h"
+
 namespace WTFNoncopyable {
 
 namespace WTFNoncopyable {
 
-    class Noncopyable {
+    class Noncopyable : public FastAllocBase {
         Noncopyable(const Noncopyable&);
         Noncopyable& operator=(const Noncopyable&);
     protected:
         Noncopyable(const Noncopyable&);
         Noncopyable& operator=(const Noncopyable&);
     protected:
@@ -34,8 +36,17 @@ namespace WTFNoncopyable {
         ~Noncopyable() { }
     };
 
         ~Noncopyable() { }
     };
 
+    class NoncopyableCustomAllocated {
+        NoncopyableCustomAllocated(const NoncopyableCustomAllocated&);
+        NoncopyableCustomAllocated& operator=(const NoncopyableCustomAllocated&);
+    protected:
+        NoncopyableCustomAllocated() { }
+        ~NoncopyableCustomAllocated() { }
+    };
+
 } // namespace WTFNoncopyable
 
 using WTFNoncopyable::Noncopyable;
 } // namespace WTFNoncopyable
 
 using WTFNoncopyable::Noncopyable;
+using WTFNoncopyable::NoncopyableCustomAllocated;
 
 #endif // WTF_Noncopyable_h
 
 #endif // WTF_Noncopyable_h
index 344f813f2642c711652f71fa8b8e1677fde66619..61375c7691c163eaeb7b6415b1b23de97a70d665 100644 (file)
@@ -27,7 +27,7 @@
 
 namespace WTF {
 
 
 namespace WTF {
 
-    template <typename T> class OwnArrayPtr : Noncopyable {
+    template <typename T> class OwnArrayPtr : public Noncopyable {
     public:
         explicit OwnArrayPtr(T* ptr = 0) : m_ptr(ptr) { }
         ~OwnArrayPtr() { safeDelete(); }
     public:
         explicit OwnArrayPtr(T* ptr = 0) : m_ptr(ptr) { }
         ~OwnArrayPtr() { safeDelete(); }
@@ -46,8 +46,12 @@ namespace WTF {
         bool operator!() const { return !m_ptr; }
 
         // This conversion operator allows implicit conversion to bool but not to other integer types.
         bool operator!() const { return !m_ptr; }
 
         // This conversion operator allows implicit conversion to bool but not to other integer types.
+#if COMPILER(WINSCW)
+        operator bool() const { return m_ptr; }
+#else
         typedef T* OwnArrayPtr::*UnspecifiedBoolType;
         operator UnspecifiedBoolType() const { return m_ptr ? &OwnArrayPtr::m_ptr : 0; }
         typedef T* OwnArrayPtr::*UnspecifiedBoolType;
         operator UnspecifiedBoolType() const { return m_ptr ? &OwnArrayPtr::m_ptr : 0; }
+#endif
 
         void swap(OwnArrayPtr& o) { std::swap(m_ptr, o.m_ptr); }
 
 
         void swap(OwnArrayPtr& o) { std::swap(m_ptr, o.m_ptr); }
 
index 5c0d0647bf4f469cac84ab5e1e86b98fc6f593d5..c88235a8a9407ce780f045bba1e227a72ef8b83f 100644 (file)
@@ -27,7 +27,7 @@
 
 namespace WTF {
 
 
 namespace WTF {
 
-    template<class T> class OwnFastMallocPtr : Noncopyable {
+    template<class T> class OwnFastMallocPtr : public Noncopyable {
     public:
         explicit OwnFastMallocPtr(T* ptr) : m_ptr(ptr)
         {
     public:
         explicit OwnFastMallocPtr(T* ptr) : m_ptr(ptr)
         {
index 9e4bd32ae82a47e79a81724207a15af7891ddcfd..b7e62b1eab130ea41b67505a4318009a6c76c2b9 100644 (file)
@@ -34,7 +34,7 @@ namespace WTF {
 
     template <typename T> class PassOwnPtr;
 
 
     template <typename T> class PassOwnPtr;
 
-    template <typename T> class OwnPtr : Noncopyable {
+    template <typename T> class OwnPtr : public Noncopyable {
     public:
         typedef typename RemovePointer<T>::Type ValueType;
         typedef ValueType* PtrType;
     public:
         typedef typename RemovePointer<T>::Type ValueType;
         typedef ValueType* PtrType;
index d80ed629133320a6576fa05b15e916cce189acf2..36ba78e168f9ab6aa83f3a354f3280d0965d68b4 100644 (file)
@@ -28,6 +28,19 @@ namespace WTF {
     template<typename T> class RefPtr;
     template<typename T> class PassRefPtr;
     template <typename T> PassRefPtr<T> adoptRef(T*);
     template<typename T> class RefPtr;
     template<typename T> class PassRefPtr;
     template <typename T> PassRefPtr<T> adoptRef(T*);
+    
+    // Remove inline for winscw compiler to prevent the compiler agressively resolving 
+    // T::deref(), which will fail compiling when PassRefPtr<T> is used as class member 
+    // or function arguments before T is defined.
+    template<typename T> 
+#if !COMPILER(WINSCW)
+    inline 
+#endif
+    void derefIfNotNull(T* ptr)
+    {
+        if (UNLIKELY(ptr != 0))
+            ptr->deref();
+    }
 
     template<typename T> class PassRefPtr {
     public:
 
     template<typename T> class PassRefPtr {
     public:
@@ -40,8 +53,8 @@ namespace WTF {
         PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {}
         template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { }
 
         PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {}
         template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { }
 
-        ALWAYS_INLINE ~PassRefPtr() { if (UNLIKELY(m_ptr != 0)) m_ptr->deref(); }
-        
+        ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull<T>(m_ptr); }
+
         template <class U> 
         PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); }
         
         template <class U> 
         PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); }
         
@@ -56,12 +69,9 @@ namespace WTF {
         bool operator!() const { return !m_ptr; }
 
         // This conversion operator allows implicit conversion to bool but not to other integer types.
         bool operator!() const { return !m_ptr; }
 
         // This conversion operator allows implicit conversion to bool but not to other integer types.
-#if COMPILER(WINSCW)
-        operator bool() const { return m_ptr; }
-#else
-        typedef T* PassRefPtr::*UnspecifiedBoolType;
+        typedef T* (PassRefPtr::*UnspecifiedBoolType);
         operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
         operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
-#endif
+
         PassRefPtr& operator=(T*);
         PassRefPtr& operator=(const PassRefPtr&);
         template <typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
         PassRefPtr& operator=(T*);
         PassRefPtr& operator=(const PassRefPtr&);
         template <typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
@@ -74,6 +84,62 @@ namespace WTF {
         mutable T* m_ptr;
     };
     
         mutable T* m_ptr;
     };
     
+    // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr
+    // begins life non-null, and can only become null through a call to releaseRef()
+    // or clear().
+
+    // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However,
+    // if we use inheritance, GCC's optimizer fails to realize that destruction
+    // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the
+    // most important code from PassRefPtr.
+    template <typename T> class NonNullPassRefPtr {
+    public:
+        NonNullPassRefPtr(T* ptr)
+            : m_ptr(ptr)
+        {
+            ASSERT(m_ptr);
+            m_ptr->ref();
+        }
+
+        template <class U> NonNullPassRefPtr(const RefPtr<U>& o)
+            : m_ptr(o.get())
+        {
+            ASSERT(m_ptr);
+            m_ptr->ref();
+        }
+
+        NonNullPassRefPtr(const NonNullPassRefPtr& o)
+            : m_ptr(o.releaseRef())
+        {
+            ASSERT(m_ptr);
+        }
+
+        template <class U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
+            : m_ptr(o.releaseRef())
+        {
+            ASSERT(m_ptr);
+        }
+
+        template <class U> NonNullPassRefPtr(const PassRefPtr<U>& o)
+            : m_ptr(o.releaseRef())
+        {
+            ASSERT(m_ptr);
+        }
+
+        ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); }
+
+        T* get() const { return m_ptr; }
+
+        void clear() { derefIfNotNull(m_ptr); m_ptr = 0; }
+        T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; }
+
+        T& operator*() const { return *m_ptr; }
+        T* operator->() const { return m_ptr; }
+
+    private:
+        mutable T* m_ptr;
+    };
+
     template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o) 
     {
         T* optr = o.get();
     template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o) 
     {
         T* optr = o.get();
@@ -188,6 +254,7 @@ namespace WTF {
 } // namespace WTF
 
 using WTF::PassRefPtr;
 } // namespace WTF
 
 using WTF::PassRefPtr;
+using WTF::NonNullPassRefPtr;
 using WTF::adoptRef;
 using WTF::static_pointer_cast;
 using WTF::const_pointer_cast;
 using WTF::adoptRef;
 using WTF::static_pointer_cast;
 using WTF::const_pointer_cast;
index e4d41fe8c4688408004b1756257cab169544b439..cf6c86355520cfc7fbdbf3c79ddfbd82c80e1ece 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc.  All rights reserved.
 /*
  * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc.  All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef WTF_Platform_h
 #define WTF_Platform_h
 
 #ifndef WTF_Platform_h
 #define WTF_Platform_h
 
-/* PLATFORM handles OS, operating environment, graphics API, and CPU */
-#define PLATFORM(WTF_FEATURE) (defined( WTF_PLATFORM_##WTF_FEATURE ) && WTF_PLATFORM_##WTF_FEATURE)
-#define COMPILER(WTF_FEATURE) (defined( WTF_COMPILER_##WTF_FEATURE ) && WTF_COMPILER_##WTF_FEATURE)
-#define HAVE(WTF_FEATURE) (defined( HAVE_##WTF_FEATURE ) && HAVE_##WTF_FEATURE)
-#define USE(WTF_FEATURE) (defined( WTF_USE_##WTF_FEATURE ) && WTF_USE_##WTF_FEATURE)
-#define ENABLE(WTF_FEATURE) (defined( ENABLE_##WTF_FEATURE ) && ENABLE_##WTF_FEATURE)
+/* ==== PLATFORM handles OS, operating environment, graphics API, and
+   CPU. This macro will be phased out in favor of platform adaptation
+   macros, policy decision macros, and top-level port definitions. ==== */
+#define PLATFORM(WTF_FEATURE) (defined WTF_PLATFORM_##WTF_FEATURE  && WTF_PLATFORM_##WTF_FEATURE)
 
 
-/* Operating systems - low-level dependencies */
 
 
-/* PLATFORM(DARWIN) */
-/* Operating system level dependencies for Mac OS X / Darwin that should */
-/* be used regardless of operating environment */
+/* ==== Platform adaptation macros: these describe properties of the target environment. ==== */
+
+/* COMPILER() - the compiler being used to build the project */
+#define COMPILER(WTF_FEATURE) (defined WTF_COMPILER_##WTF_FEATURE  && WTF_COMPILER_##WTF_FEATURE)
+/* CPU() - the target CPU architecture */
+#define CPU(WTF_FEATURE) (defined WTF_CPU_##WTF_FEATURE  && WTF_CPU_##WTF_FEATURE)
+/* HAVE() - specific system features (headers, functions or similar) that are present or not */
+#define HAVE(WTF_FEATURE) (defined HAVE_##WTF_FEATURE  && HAVE_##WTF_FEATURE)
+/* OS() - underlying operating system; only to be used for mandated low-level services like 
+   virtual memory, not to choose a GUI toolkit */
+#define OS(WTF_FEATURE) (defined WTF_OS_##WTF_FEATURE  && WTF_OS_##WTF_FEATURE)
+
+
+/* ==== Policy decision macros: these define policy choices for a particular port. ==== */
+
+/* USE() - use a particular third-party library or optional OS service */
+#define USE(WTF_FEATURE) (defined WTF_USE_##WTF_FEATURE  && WTF_USE_##WTF_FEATURE)
+/* ENABLE() - turn on a specific feature of WebKit */
+#define ENABLE(WTF_FEATURE) (defined ENABLE_##WTF_FEATURE  && ENABLE_##WTF_FEATURE)
+
+
+
+/* ==== COMPILER() - the compiler being used to build the project ==== */
+
+/* COMPILER(MSVC) Microsoft Visual C++ */
+/* COMPILER(MSVC7) Microsoft Visual C++ v7 or lower*/
+#if defined(_MSC_VER)
+#define WTF_COMPILER_MSVC 1
+#if _MSC_VER < 1400
+#define WTF_COMPILER_MSVC7 1
+#endif
+#endif
+
+/* COMPILER(RVCT)  - ARM RealView Compilation Tools */
+#if defined(__CC_ARM) || defined(__ARMCC__)
+#define WTF_COMPILER_RVCT 1
+#endif
+
+/* COMPILER(GCC) - GNU Compiler Collection */
+/* --gnu option of the RVCT compiler also defines __GNUC__ */
+#if defined(__GNUC__) && !COMPILER(RVCT)
+#define WTF_COMPILER_GCC 1
+#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif
+
+/* COMPILER(MINGW) - MinGW GCC */
+#if defined(MINGW) || defined(__MINGW32__)
+#define WTF_COMPILER_MINGW 1
+#endif
+
+/* COMPILER(WINSCW) - CodeWarrior for Symbian emulator */
+#if defined(__WINSCW__)
+#define WTF_COMPILER_WINSCW 1
+#endif
+
+
+
+/* ==== CPU() - the target CPU architecture ==== */
+
+/* This also defines CPU(BIG_ENDIAN) or CPU(MIDDLE_ENDIAN) or neither, as appropriate. */
+
+/* CPU(ALPHA) - DEC Alpha */
+#if defined(__alpha__)
+#define WTF_CPU_ALPHA 1
+#endif
+
+/* CPU(IA64) - Itanium / IA-64 */
+#if defined(__ia64__)
+#define WTF_CPU_IA64 1
+#endif
+
+/* CPU(PPC) - PowerPC 32-bit */
+#if   defined(__ppc__)     \
+    || defined(__PPC__)     \
+    || defined(__powerpc__) \
+    || defined(__powerpc)   \
+    || defined(__POWERPC__) \
+    || defined(_M_PPC)      \
+    || defined(__PPC)
+#define WTF_CPU_PPC 1
+#define WTF_CPU_BIG_ENDIAN 1
+#endif
+
+/* CPU(PPC64) - PowerPC 64-bit */
+#if   defined(__ppc64__) \
+    || defined(__PPC64__)
+#define WTF_CPU_PPC64 1
+#define WTF_CPU_BIG_ENDIAN 1
+#endif
+
+/* CPU(SH4) - SuperH SH-4 */
+#if defined(__SH4__)
+#define WTF_CPU_SH4 1
+#endif
+
+/* CPU(SPARC32) - SPARC 32-bit */
+#if defined(__sparc) && !defined(__arch64__) || defined(__sparcv8)
+#define WTF_CPU_SPARC32 1
+#define WTF_CPU_BIG_ENDIAN 1
+#endif
+
+/* CPU(SPARC64) - SPARC 64-bit */
+#if defined(__sparc__) && defined(__arch64__) || defined (__sparcv9)
+#define WTF_CPU_SPARC64 1
+#define WTF_CPU_BIG_ENDIAN 1
+#endif
+
+/* CPU(SPARC) - any SPARC, true for CPU(SPARC32) and CPU(SPARC64) */
+#if CPU(SPARC32) || CPU(SPARC64)
+#define WTF_CPU_SPARC
+#endif
+
+/* CPU(X86) - i386 / x86 32-bit */
+#if   defined(__i386__) \
+    || defined(i386)     \
+    || defined(_M_IX86)  \
+    || defined(_X86_)    \
+    || defined(__THW_INTEL)
+#define WTF_CPU_X86 1
+#endif
+
+/* CPU(X86_64) - AMD64 / Intel64 / x86_64 64-bit */
+#if   defined(__x86_64__) \
+    || defined(_M_X64)
+#define WTF_CPU_X86_64 1
+#endif
+
+/* CPU(ARM) - ARM, any version*/
+#if   defined(arm) \
+    || defined(__arm__)
+#define WTF_CPU_ARM 1
+
+#if defined(__ARMEB__)
+#define WTF_CPU_BIG_ENDIAN 1
+
+#elif !defined(__ARM_EABI__) \
+    && !defined(__EABI__) \
+    && !defined(__VFP_FP__) \
+    && !defined(ANDROID)
+#define WTF_CPU_MIDDLE_ENDIAN 1
+
+#endif
+
+#define WTF_ARM_ARCH_AT_LEAST(N) (CPU(ARM) && WTF_ARM_ARCH_VERSION >= N)
+
+/* Set WTF_ARM_ARCH_VERSION */
+#if   defined(__ARM_ARCH_4__) \
+    || defined(__ARM_ARCH_4T__) \
+    || defined(__MARM_ARMV4__) \
+    || defined(_ARMV4I_)
+#define WTF_ARM_ARCH_VERSION 4
+
+#elif defined(__ARM_ARCH_5__) \
+    || defined(__ARM_ARCH_5T__) \
+    || defined(__ARM_ARCH_5E__) \
+    || defined(__ARM_ARCH_5TE__) \
+    || defined(__ARM_ARCH_5TEJ__) \
+    || defined(__MARM_ARMV5__)
+#define WTF_ARM_ARCH_VERSION 5
+
+#elif defined(__ARM_ARCH_6__) \
+    || defined(__ARM_ARCH_6J__) \
+    || defined(__ARM_ARCH_6K__) \
+    || defined(__ARM_ARCH_6Z__) \
+    || defined(__ARM_ARCH_6ZK__) \
+    || defined(__ARM_ARCH_6T2__) \
+    || defined(__ARMV6__)
+#define WTF_ARM_ARCH_VERSION 6
+
+#elif defined(__ARM_ARCH_7A__) \
+    || defined(__ARM_ARCH_7R__)
+#define WTF_ARM_ARCH_VERSION 7
+
+/* RVCT sets _TARGET_ARCH_ARM */
+#elif defined(__TARGET_ARCH_ARM)
+#define WTF_ARM_ARCH_VERSION __TARGET_ARCH_ARM
+
+#else
+#define WTF_ARM_ARCH_VERSION 0
+
+#endif
+
+/* Set WTF_THUMB_ARCH_VERSION */
+#if   defined(__ARM_ARCH_4T__)
+#define WTF_THUMB_ARCH_VERSION 1
+
+#elif defined(__ARM_ARCH_5T__) \
+    || defined(__ARM_ARCH_5TE__) \
+    || defined(__ARM_ARCH_5TEJ__)
+#define WTF_THUMB_ARCH_VERSION 2
+
+#elif defined(__ARM_ARCH_6J__) \
+    || defined(__ARM_ARCH_6K__) \
+    || defined(__ARM_ARCH_6Z__) \
+    || defined(__ARM_ARCH_6ZK__) \
+    || defined(__ARM_ARCH_6M__)
+#define WTF_THUMB_ARCH_VERSION 3
+
+#elif defined(__ARM_ARCH_6T2__) \
+    || defined(__ARM_ARCH_7__) \
+    || defined(__ARM_ARCH_7A__) \
+    || defined(__ARM_ARCH_7R__) \
+    || defined(__ARM_ARCH_7M__)
+#define WTF_THUMB_ARCH_VERSION 4
+
+/* RVCT sets __TARGET_ARCH_THUMB */
+#elif defined(__TARGET_ARCH_THUMB)
+#define WTF_THUMB_ARCH_VERSION __TARGET_ARCH_THUMB
+
+#else
+#define WTF_THUMB_ARCH_VERSION 0
+#endif
+
+
+/* CPU(ARMV5_OR_LOWER) - ARM instruction set v5 or earlier */
+/* On ARMv5 and below the natural alignment is required. 
+   And there are some other differences for v5 or earlier. */
+#if !defined(ARMV5_OR_LOWER) && !WTF_ARM_ARCH_AT_LEAST(6)
+#define WTF_CPU_ARMV5_OR_LOWER 1
+#endif
+
+
+/* CPU(ARM_TRADITIONAL) - Thumb2 is not available, only traditional ARM (v4 or greater) */
+/* CPU(ARM_THUMB2) - Thumb2 instruction set is available */
+/* Only one of these will be defined. */
+#if !defined(WTF_CPU_ARM_TRADITIONAL) && !defined(WTF_CPU_ARM_THUMB2)
+#  if defined(thumb2) || defined(__thumb2__) \
+    || ((defined(__thumb) || defined(__thumb__)) && WTF_THUMB_ARCH_VERSION == 4)
+#    define WTF_CPU_ARM_TRADITIONAL 0
+#    define WTF_CPU_ARM_THUMB2 1
+#  elif WTF_ARM_ARCH_AT_LEAST(4)
+#    define WTF_CPU_ARM_TRADITIONAL 1
+#    define WTF_CPU_ARM_THUMB2 0
+#  else
+#    error "Not supported ARM architecture"
+#  endif
+#elif CPU(ARM_TRADITIONAL) && CPU(ARM_THUMB2) /* Sanity Check */
+#  error "Cannot use both of WTF_CPU_ARM_TRADITIONAL and WTF_CPU_ARM_THUMB2 platforms"
+#endif /* !defined(WTF_CPU_ARM_TRADITIONAL) && !defined(WTF_CPU_ARM_THUMB2) */
+
+#endif /* ARM */
+
+
+
+/* ==== OS() - underlying operating system; only to be used for mandated low-level services like 
+   virtual memory, not to choose a GUI toolkit ==== */
+
+/* OS(ANDROID) - Android */
+#ifdef ANDROID
+#define WTF_OS_ANDROID 1
+#endif
+
+/* OS(AIX) - AIX */
+#ifdef _AIX
+#define WTF_OS_AIX 1
+#endif
+
+/* OS(DARWIN) - Any Darwin-based OS, including Mac OS X and iPhone OS */
 #ifdef __APPLE__
 #ifdef __APPLE__
-#define WTF_PLATFORM_DARWIN 1
+#define WTF_OS_DARWIN 1
+
+/* FIXME: BUILDING_ON_.., and TARGETING... macros should be folded into the OS() system */
 #include <AvailabilityMacros.h>
 #if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
 #define BUILDING_ON_TIGER 1
 #elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
 #define BUILDING_ON_LEOPARD 1
 #include <AvailabilityMacros.h>
 #if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
 #define BUILDING_ON_TIGER 1
 #elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
 #define BUILDING_ON_LEOPARD 1
+#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+#define BUILDING_ON_SNOW_LEOPARD 1
+#endif
+#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+#define TARGETING_TIGER 1
+#elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+#define TARGETING_LEOPARD 1
+#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
+#define TARGETING_SNOW_LEOPARD 1
 #endif
 #include <Availability.h>
 #include <TargetConditionals.h>
 #endif
 #include <Availability.h>
 #include <TargetConditionals.h>
+
 #endif
 
 #endif
 
-/* PLATFORM(WIN_OS) */
-/* Operating system level dependencies for Windows that should be used */
-/* regardless of operating environment */
-#if defined(WIN32) || defined(_WIN32)
-#define WTF_PLATFORM_WIN_OS 1
+/* OS(IPHONE_OS) - iPhone OS */
+/* OS(MAC_OS_X) - Mac OS X (not including iPhone OS) */
+#if OS(DARWIN) && ((defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED)  \
+    || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)                   \
+    || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR))
+#define WTF_OS_IPHONE_OS 1
+#elif OS(DARWIN) && defined(TARGET_OS_MAC) && TARGET_OS_MAC
+#define WTF_OS_MAC_OS_X 1
 #endif
 
 #endif
 
-/* PLATFORM(WINCE) */
-/* Operating system level dependencies for Windows CE that should be used */
-/* regardless of operating environment */
-/* Note that for this platform PLATFORM(WIN_OS) is also defined. */
-#if defined(_WIN32_WCE)
-#define WTF_PLATFORM_WINCE 1
+/* OS(FREEBSD) - FreeBSD */
+#ifdef __FreeBSD__
+#define WTF_OS_FREEBSD 1
+#endif
+
+/* OS(HAIKU) - Haiku */
+#ifdef __HAIKU__
+#define WTF_OS_HAIKU 1
 #endif
 
 #endif
 
-/* PLATFORM(LINUX) */
-/* Operating system level dependencies for Linux-like systems that */
-/* should be used regardless of operating environment */
+/* OS(LINUX) - Linux */
 #ifdef __linux__
 #ifdef __linux__
-#define WTF_PLATFORM_LINUX 1
+#define WTF_OS_LINUX 1
 #endif
 
 #endif
 
-/* PLATFORM(FREEBSD) */
-/* Operating system level dependencies for FreeBSD-like systems that */
-/* should be used regardless of operating environment */
-#ifdef __FreeBSD__
-#define WTF_PLATFORM_FREEBSD 1
+/* OS(NETBSD) - NetBSD */
+#if defined(__NetBSD__)
+#define WTF_PLATFORM_NETBSD 1
 #endif
 
 #endif
 
-/* PLATFORM(OPENBSD) */
-/* Operating system level dependencies for OpenBSD systems that */
-/* should be used regardless of operating environment */
+/* OS(OPENBSD) - OpenBSD */
 #ifdef __OpenBSD__
 #ifdef __OpenBSD__
-#define WTF_PLATFORM_OPENBSD 1
+#define WTF_OS_OPENBSD 1
 #endif
 
 #endif
 
-/* PLATFORM(SOLARIS) */
-/* Operating system level dependencies for Solaris that should be used */
-/* regardless of operating environment */
-#if defined(sun) || defined(__sun)
-#define WTF_PLATFORM_SOLARIS 1
+/* OS(QNX) - QNX */
+#if defined(__QNXNTO__)
+#define WTF_OS_QNX 1
 #endif
 
 #endif
 
-#if defined (__S60__) || defined (__SYMBIAN32__)
-/* we are cross-compiling, it is not really windows */
-#undef WTF_PLATFORM_WIN_OS
-#undef WTF_PLATFORM_WIN
-#undef WTF_PLATFORM_CAIRO
-#define WTF_PLATFORM_S60 1
-#define WTF_PLATFORM_SYMBIAN 1
+/* OS(SOLARIS) - Solaris */
+#if defined(sun) || defined(__sun)
+#define WTF_OS_SOLARIS 1
 #endif
 
 #endif
 
+/* OS(WINCE) - Windows CE; note that for this platform OS(WINDOWS) is also defined */
+#if defined(_WIN32_WCE)
+#define WTF_OS_WINCE 1
+#endif
 
 
-/* PLATFORM(NETBSD) */
-/* Operating system level dependencies for NetBSD that should be used */
-/* regardless of operating environment */
-#if defined(__NetBSD__)
-#define WTF_PLATFORM_NETBSD 1
+/* OS(WINDOWS) - Any version of Windows */
+#if defined(WIN32) || defined(_WIN32)
+#define WTF_OS_WINDOWS 1
 #endif
 
 #endif
 
-/* PLATFORM(UNIX) */
-/* Operating system level dependencies for Unix-like systems that */
-/* should be used regardless of operating environment */
-#if   PLATFORM(DARWIN)     \
-   || PLATFORM(FREEBSD)    \
-   || PLATFORM(S60)        \
-   || PLATFORM(NETBSD)     \
-   || defined(unix)        \
-   || defined(__unix)      \
-   || defined(__unix__)    \
-   || defined(_AIX)
-#define WTF_PLATFORM_UNIX 1
+/* OS(SYMBIAN) - Symbian */
+#if defined (__SYMBIAN32__)
+/* we are cross-compiling, it is not really windows */
+#undef WTF_OS_WINDOWS
+#undef WTF_PLATFORM_WIN
+#define WTF_OS_SYMBIAN 1
+#endif
+
+/* OS(UNIX) - Any Unix-like system */
+#if   OS(AIX)              \
+    || OS(ANDROID)          \
+    || OS(DARWIN)           \
+    || OS(FREEBSD)          \
+    || OS(HAIKU)            \
+    || OS(LINUX)            \
+    || OS(NETBSD)           \
+    || OS(OPENBSD)          \
+    || OS(QNX)              \
+    || OS(SOLARIS)          \
+    || OS(SYMBIAN)          \
+    || defined(unix)        \
+    || defined(__unix)      \
+    || defined(__unix__)
+#define WTF_OS_UNIX 1
 #endif
 
 /* Operating environments */
 
 #endif
 
 /* Operating environments */
 
+/* FIXME: these are all mixes of OS, operating environment and policy choices. */
 /* PLATFORM(CHROMIUM) */
 /* PLATFORM(QT) */
 /* PLATFORM(CHROMIUM) */
 /* PLATFORM(QT) */
+/* PLATFORM(WX) */
 /* PLATFORM(GTK) */
 /* PLATFORM(GTK) */
+/* PLATFORM(HAIKU) */
 /* PLATFORM(MAC) */
 /* PLATFORM(WIN) */
 #if defined(BUILDING_CHROMIUM__)
 #define WTF_PLATFORM_CHROMIUM 1
 #elif defined(BUILDING_QT__)
 #define WTF_PLATFORM_QT 1
 /* PLATFORM(MAC) */
 /* PLATFORM(WIN) */
 #if defined(BUILDING_CHROMIUM__)
 #define WTF_PLATFORM_CHROMIUM 1
 #elif defined(BUILDING_QT__)
 #define WTF_PLATFORM_QT 1
-
-/* PLATFORM(KDE) */
-#if defined(BUILDING_KDE__)
-#define WTF_PLATFORM_KDE 1
-#endif
-
 #elif defined(BUILDING_WX__)
 #define WTF_PLATFORM_WX 1
 #elif defined(BUILDING_GTK__)
 #define WTF_PLATFORM_GTK 1
 #elif defined(BUILDING_WX__)
 #define WTF_PLATFORM_WX 1
 #elif defined(BUILDING_GTK__)
 #define WTF_PLATFORM_GTK 1
-#elif PLATFORM(DARWIN)
+#elif defined(BUILDING_HAIKU__)
+#define WTF_PLATFORM_HAIKU 1
+#elif OS(DARWIN)
 #define WTF_PLATFORM_MAC 1
 #define WTF_PLATFORM_MAC 1
-#elif PLATFORM(WIN_OS)
+#elif OS(WINDOWS)
 #define WTF_PLATFORM_WIN 1
 #endif
 
 /* PLATFORM(IPHONE) */
 #define WTF_PLATFORM_WIN 1
 #endif
 
 /* PLATFORM(IPHONE) */
+/* FIXME: this is sometimes used as an OS switch and sometimes for higher-level things */
 #if (defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
 #define WTF_PLATFORM_IPHONE 1
 #endif
 #if (defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
 #define WTF_PLATFORM_IPHONE 1
 #endif
 #define WTF_PLATFORM_IPHONE 0
 #endif
 
 #define WTF_PLATFORM_IPHONE 0
 #endif
 
+/* PLATFORM(ANDROID) */
+/* FIXME: this is sometimes used as an OS() switch, and other times to drive
+   policy choices */
+#if defined(ANDROID)
+#define WTF_PLATFORM_ANDROID 1
+#endif
+
 /* Graphics engines */
 
 /* PLATFORM(CG) and PLATFORM(CI) */
 /* Graphics engines */
 
 /* PLATFORM(CG) and PLATFORM(CI) */
 
 /* PLATFORM(SKIA) for Win/Linux, CG/CI for Mac */
 #if PLATFORM(CHROMIUM)
 
 /* PLATFORM(SKIA) for Win/Linux, CG/CI for Mac */
 #if PLATFORM(CHROMIUM)
-#if PLATFORM(DARWIN)
+#define ENABLE_HISTORY_ALWAYS_ASYNC 1
+#if OS(DARWIN)
 #define WTF_PLATFORM_CG 1
 #define WTF_PLATFORM_CI 1
 #define WTF_USE_ATSUI 1
 #define WTF_PLATFORM_CG 1
 #define WTF_PLATFORM_CI 1
 #define WTF_USE_ATSUI 1
+#define WTF_USE_CORE_TEXT 1
 #else
 #define WTF_PLATFORM_SKIA 1
 #endif
 #endif
 
 #else
 #define WTF_PLATFORM_SKIA 1
 #endif
 #endif
 
-/* Makes PLATFORM(WIN) default to PLATFORM(CAIRO) */
-/* FIXME: This should be changed from a blacklist to a whitelist */
-#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(WX) && !PLATFORM(CHROMIUM)
+#if PLATFORM(GTK)
 #define WTF_PLATFORM_CAIRO 1
 #endif
 
 #define WTF_PLATFORM_CAIRO 1
 #endif
 
-/* CPU */
-
-/* PLATFORM(PPC) */
-#if   defined(__ppc__)     \
-   || defined(__PPC__)     \
-   || defined(__powerpc__) \
-   || defined(__powerpc)   \
-   || defined(__POWERPC__) \
-   || defined(_M_PPC)      \
-   || defined(__PPC)
-#define WTF_PLATFORM_PPC 1
-#define WTF_PLATFORM_BIG_ENDIAN 1
-#endif
-
-/* PLATFORM(PPC64) */
-#if   defined(__ppc64__) \
-   || defined(__PPC64__)
-#define WTF_PLATFORM_PPC64 1
-#define WTF_PLATFORM_BIG_ENDIAN 1
-#endif
-
-/* PLATFORM(ARM) */
-#if   defined(arm) \
-   || defined(__arm__)
-#define WTF_PLATFORM_ARM 1
-#if defined(__ARMEB__)
-#define WTF_PLATFORM_BIG_ENDIAN 1
-#elif !defined(__ARM_EABI__) && !defined(__ARMEB__) && !defined(__VFP_FP__)
-#define WTF_PLATFORM_MIDDLE_ENDIAN 1
-#endif
-#if !defined(__ARM_EABI__)
-#define WTF_PLATFORM_FORCE_PACK 1
-#endif
-#define ARM_ARCH_VERSION 3
-#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
-#undef ARM_ARCH_VERSION
-#define ARM_ARCH_VERSION 4
-#endif
-#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
-        || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
-        || defined(__ARM_ARCH_5TEJ__)
-#undef ARM_ARCH_VERSION
-#define ARM_ARCH_VERSION 5
-#endif
-#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
-     || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
-     || defined(__ARM_ARCH_6ZK__)
-#undef ARM_ARCH_VERSION
-#define ARM_ARCH_VERSION 6
-#endif
-#if defined(__ARM_ARCH_7A__)
-#undef ARM_ARCH_VERSION
-#define ARM_ARCH_VERSION 7
-#endif
-#endif /* ARM */
-#define PLATFORM_ARM_ARCH(N) (PLATFORM(ARM) && ARM_ARCH_VERSION >= N)
-
-/* PLATFORM(X86) */
-#if   defined(__i386__) \
-   || defined(i386)     \
-   || defined(_M_IX86)  \
-   || defined(_X86_)    \
-   || defined(__THW_INTEL)
-#define WTF_PLATFORM_X86 1
-#endif
-
-/* PLATFORM(X86_64) */
-#if   defined(__x86_64__) \
-   || defined(_M_X64)
-#define WTF_PLATFORM_X86_64 1
-#endif
 
 
-/* PLATFORM(SH4) */
-#if defined(__SH4__)
-#define WTF_PLATFORM_SH4 1
-#endif
-
-/* PLATFORM(SPARC64) */
-#if defined(__sparc64__)
-#define WTF_PLATFORM_SPARC64 1
-#define WTF_PLATFORM_BIG_ENDIAN 1
-#endif
-
-/* PLATFORM(WINCE) && PLATFORM(QT)
+/* OS(WINCE) && PLATFORM(QT)
    We can not determine the endianess at compile time. For
    Qt for Windows CE the endianess is specified in the
    device specific makespec
 */
    We can not determine the endianess at compile time. For
    Qt for Windows CE the endianess is specified in the
    device specific makespec
 */
-#if PLATFORM(WINCE) && PLATFORM(QT)
+#if OS(WINCE) && PLATFORM(QT)
 #   include <QtGlobal>
 #   undef WTF_PLATFORM_BIG_ENDIAN
 #   undef WTF_PLATFORM_MIDDLE_ENDIAN
 #   if Q_BYTE_ORDER == Q_BIG_EDIAN
 #       define WTF_PLATFORM_BIG_ENDIAN 1
 #   endif
 #   include <QtGlobal>
 #   undef WTF_PLATFORM_BIG_ENDIAN
 #   undef WTF_PLATFORM_MIDDLE_ENDIAN
 #   if Q_BYTE_ORDER == Q_BIG_EDIAN
 #       define WTF_PLATFORM_BIG_ENDIAN 1
 #   endif
-#endif
 
 
-/* Compiler */
-
-/* COMPILER(MSVC) */
-#if defined(_MSC_VER)
-#define WTF_COMPILER_MSVC 1
-#if _MSC_VER < 1400
-#define WTF_COMPILER_MSVC7 1
-#endif
+#   include <ce_time.h>
 #endif
 
 #endif
 
-/* COMPILER(RVCT) */
-#if defined(__CC_ARM) || defined(__ARMCC__)
-#define WTF_COMPILER_RVCT 1
+#if (PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN) || (PLATFORM(QT) && OS(DARWIN) && !ENABLE(SINGLE_THREADED))) && !defined(ENABLE_JSC_MULTIPLE_THREADS)
+#define ENABLE_JSC_MULTIPLE_THREADS 1
 #endif
 
 #endif
 
-/* COMPILER(GCC) */
-/* --gnu option of the RVCT compiler also defines __GNUC__ */
-#if defined(__GNUC__) && !COMPILER(RVCT)
-#define WTF_COMPILER_GCC 1
+/* On Windows, use QueryPerformanceCounter by default */
+#if OS(WINDOWS)
+#define WTF_USE_QUERY_PERFORMANCE_COUNTER  1
 #endif
 
 #endif
 
-/* COMPILER(MINGW) */
-#if defined(MINGW) || defined(__MINGW32__)
-#define WTF_COMPILER_MINGW 1
-#endif
+#if OS(WINCE) && !PLATFORM(QT)
+#undef ENABLE_JSC_MULTIPLE_THREADS
+#define ENABLE_JSC_MULTIPLE_THREADS        0
+#define USE_SYSTEM_MALLOC                  0
+#define ENABLE_ICONDATABASE                0
+#define ENABLE_JAVASCRIPT_DEBUGGER         0
+#define ENABLE_FTPDIR                      0
+#define ENABLE_PAN_SCROLLING               0
+#define ENABLE_WML                         1
+#define HAVE_ACCESSIBILITY                 0
 
 
-/* COMPILER(BORLAND) */
-/* not really fully supported - is this relevant any more? */
-#if defined(__BORLANDC__)
-#define WTF_COMPILER_BORLAND 1
-#endif
+#define NOMINMAX       /* Windows min and max conflict with standard macros */
+#define NOSHLWAPI      /* shlwapi.h not available on WinCe */
 
 
-/* COMPILER(CYGWIN) */
-/* not really fully supported - is this relevant any more? */
-#if defined(__CYGWIN__)
-#define WTF_COMPILER_CYGWIN 1
-#endif
+/* MSDN documentation says these functions are provided with uspce.lib.  But we cannot find this file. */
+#define __usp10__      /* disable "usp10.h" */
 
 
-/* COMPILER(WINSCW) */
-#if defined(__WINSCW__)
-#define WTF_COMPILER_WINSCW 1
-#endif
+#define _INC_ASSERT    /* disable "assert.h" */
+#define assert(x)
 
 
-#if (PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS)
-#define ENABLE_JSC_MULTIPLE_THREADS 1
+/* _countof is only included in CE6; for CE5 we need to define it ourself */
+#ifndef _countof
+#define _countof(x) (sizeof(x) / sizeof((x)[0]))
 #endif
 
 #endif
 
-/* for Unicode, KDE uses Qt */
-#if PLATFORM(KDE) || PLATFORM(QT)
+#endif  /* OS(WINCE) && !PLATFORM(QT) */
+
+#if PLATFORM(QT)
 #define WTF_USE_QT4_UNICODE 1
 #define WTF_USE_QT4_UNICODE 1
-#elif PLATFORM(SYMBIAN)
-#define WTF_USE_SYMBIAN_UNICODE 1
+#elif OS(WINCE)
+#define WTF_USE_WINCE_UNICODE 1
 #elif PLATFORM(GTK)
 /* The GTK+ Unicode backend is configurable */
 #else
 #elif PLATFORM(GTK)
 /* The GTK+ Unicode backend is configurable */
 #else
 #endif
 
 
 #endif
 
 
-#if PLATFORM(CHROMIUM) && PLATFORM(DARWIN)
+#if PLATFORM(CHROMIUM) && OS(DARWIN)
 #define WTF_PLATFORM_CF 1
 #define WTF_USE_PTHREADS 1
 #define WTF_PLATFORM_CF 1
 #define WTF_USE_PTHREADS 1
+#define HAVE_PTHREAD_RWLOCK 1
 #endif
 
 #define DONT_FINALIZE_ON_MAIN_THREAD 1
 #endif
 
 #define DONT_FINALIZE_ON_MAIN_THREAD 1
+
+#if PLATFORM(QT) && OS(DARWIN)
+#define WTF_PLATFORM_CF 1
+#endif
+
 #define ENABLE_CONTEXT_MENUS 0
 #define ENABLE_DRAG_SUPPORT 0
 #define ENABLE_FTPDIR 1
 #define ENABLE_CONTEXT_MENUS 0
 #define ENABLE_DRAG_SUPPORT 0
 #define ENABLE_FTPDIR 1
 #define ENABLE_MAC_JAVA_BRIDGE 0
 #define ENABLE_NETSCAPE_PLUGIN_API 0
 #define ENABLE_ORIENTATION_EVENTS 1
 #define ENABLE_MAC_JAVA_BRIDGE 0
 #define ENABLE_NETSCAPE_PLUGIN_API 0
 #define ENABLE_ORIENTATION_EVENTS 1
+#define ENABLE_RANGETYPE_AS_TEXT 1
 #define ENABLE_REPAINT_THROTTLING 1
 #define ENABLE_RESPECT_EXIF_ORIENTATION 1
 #define ENABLE_REPAINT_THROTTLING 1
 #define ENABLE_RESPECT_EXIF_ORIENTATION 1
+#define ENABLE_YARR 0
+#define ENABLE_YARR_JIT 0
+#define HAVE_PTHREAD_RWLOCK 1
 #define HAVE_READLINE 1
 #define HAVE_RUNLOOP_TIMER 0
 #define WTF_PLATFORM_CF 1
 #define WTF_USE_PTHREADS 1
 #define HAVE_READLINE 1
 #define HAVE_RUNLOOP_TIMER 0
 #define WTF_PLATFORM_CF 1
 #define WTF_USE_PTHREADS 1
+#define WTF_USE_WEB_THREAD 1
+
+#if PLATFORM(ANDROID)
+#define WTF_USE_PTHREADS 1
+#define WTF_PLATFORM_SGL 1
+#define USE_SYSTEM_MALLOC 1
+#define ENABLE_MAC_JAVA_BRIDGE 1
+#define LOG_DISABLED 1
+/* Prevents Webkit from drawing the caret in textfields and textareas
+   This prevents unnecessary invals. */
+#define ENABLE_TEXT_CARET 1
+#define ENABLE_JAVASCRIPT_DEBUGGER 0
+#endif
 
 #if PLATFORM(WIN)
 #define WTF_USE_WININET 1
 
 #if PLATFORM(WIN)
 #define WTF_USE_WININET 1
 
 #if PLATFORM(WX)
 #define ENABLE_ASSEMBLER 1
 
 #if PLATFORM(WX)
 #define ENABLE_ASSEMBLER 1
-#define WTF_USE_CURL 1
-#define WTF_USE_PTHREADS 1
+#if OS(DARWIN)
+#define WTF_PLATFORM_CF 1
+#endif
 #endif
 
 #if PLATFORM(GTK)
 #if HAVE(PTHREAD_H)
 #define WTF_USE_PTHREADS 1
 #endif
 
 #if PLATFORM(GTK)
 #if HAVE(PTHREAD_H)
 #define WTF_USE_PTHREADS 1
+#define HAVE_PTHREAD_RWLOCK 1
 #endif
 #endif
 
 #endif
 #endif
 
+#if PLATFORM(HAIKU)
+#define HAVE_POSIX_MEMALIGN 1
+#define WTF_USE_CURL 1
+#define WTF_USE_PTHREADS 1
+#define HAVE_PTHREAD_RWLOCK 1
+#define USE_SYSTEM_MALLOC 1
+#define ENABLE_NETSCAPE_PLUGIN_API 0
+#endif
+
 #if !defined(HAVE_ACCESSIBILITY)
 #define HAVE_ACCESSIBILITY 1
 #endif /* !defined(HAVE_ACCESSIBILITY) */
 
 #if !defined(HAVE_ACCESSIBILITY)
 #define HAVE_ACCESSIBILITY 1
 #endif /* !defined(HAVE_ACCESSIBILITY) */
 
-#if PLATFORM(UNIX) && !PLATFORM(SYMBIAN)
+#if OS(UNIX) && !OS(SYMBIAN)
 #define HAVE_SIGNAL_H 1
 #endif
 
 #define HAVE_SIGNAL_H 1
 #endif
 
-#if PLATFORM(DARWIN)
+#if !OS(WINDOWS) && !OS(SOLARIS) && !OS(QNX) \
+    && !OS(SYMBIAN) && !OS(HAIKU) && !OS(RVCT) \
+    && !OS(ANDROID)
+#define HAVE_TM_GMTOFF 1
+#define HAVE_TM_ZONE 1
+#define HAVE_TIMEGM 1
+#endif
+
+#if OS(DARWIN)
 
 #define HAVE_ERRNO_H 1
 #define HAVE_LANGINFO_H 1
 
 #define HAVE_ERRNO_H 1
 #define HAVE_LANGINFO_H 1
 #define HAVE_SYS_TIME_H 1
 #define HAVE_SYS_TIMEB_H 1
 
 #define HAVE_SYS_TIME_H 1
 #define HAVE_SYS_TIMEB_H 1
 
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
+#define HAVE_DISPATCH_H 1
+
+
+#endif
 
 #define HAVE_MADV_FREE 1
 
 #define HAVE_MADV_FREE 1
+#define HAVE_PTHREAD_SETNAME_NP 1
 
 
-#elif PLATFORM(WIN_OS)
+#elif OS(WINDOWS)
 
 
-#define HAVE_FLOAT_H 1
-#if PLATFORM(WINCE)
+#if OS(WINCE)
 #define HAVE_ERRNO_H 0
 #else
 #define HAVE_SYS_TIMEB_H 1
 #endif
 #define HAVE_VIRTUALALLOC 1
 
 #define HAVE_ERRNO_H 0
 #else
 #define HAVE_SYS_TIMEB_H 1
 #endif
 #define HAVE_VIRTUALALLOC 1
 
-#elif PLATFORM(SYMBIAN)
+#elif OS(SYMBIAN)
 
 #define HAVE_ERRNO_H 1
 #define HAVE_MMAP 0
 
 #define HAVE_ERRNO_H 1
 #define HAVE_MMAP 0
 #define HAVE_SYS_PARAM_H 1
 #endif
 
 #define HAVE_SYS_PARAM_H 1
 #endif
 
+#elif OS(QNX)
+
+#define HAVE_ERRNO_H 1
+#define HAVE_MMAP 1
+#define HAVE_SBRK 1
+#define HAVE_STRINGS_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_TIME_H 1
+
+#elif OS(ANDROID)
+
+#define HAVE_ERRNO_H 1
+#define HAVE_LANGINFO_H 0
+#define HAVE_MMAP 1
+#define HAVE_SBRK 1
+#define HAVE_STRINGS_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_TIME_H 1
+
 #else
 
 /* FIXME: is this actually used or do other platforms generate their own config.h? */
 
 #define HAVE_ERRNO_H 1
 #else
 
 /* FIXME: is this actually used or do other platforms generate their own config.h? */
 
 #define HAVE_ERRNO_H 1
+/* As long as Haiku doesn't have a complete support of locale this will be disabled. */
+#if !OS(HAIKU)
 #define HAVE_LANGINFO_H 1
 #define HAVE_LANGINFO_H 1
+#endif
 #define HAVE_MMAP 1
 #define HAVE_SBRK 1
 #define HAVE_STRINGS_H 1
 #define HAVE_MMAP 1
 #define HAVE_SBRK 1
 #define HAVE_STRINGS_H 1
 #define ENABLE_FTPDIR 1
 #endif
 
 #define ENABLE_FTPDIR 1
 #endif
 
-#if !defined(ENABLE_DASHBOARD_SUPPORT)
-#define ENABLE_DASHBOARD_SUPPORT 0
-#endif
-
 #if !defined(ENABLE_CONTEXT_MENUS)
 #define ENABLE_CONTEXT_MENUS 1
 #endif
 #if !defined(ENABLE_CONTEXT_MENUS)
 #define ENABLE_CONTEXT_MENUS 1
 #endif
 #define ENABLE_DRAG_SUPPORT 1
 #endif
 
 #define ENABLE_DRAG_SUPPORT 1
 #endif
 
+#if !defined(ENABLE_DASHBOARD_SUPPORT)
+#define ENABLE_DASHBOARD_SUPPORT 0
+#endif
+
+#if !defined(ENABLE_GEOLOCATION_PERMISSION_CACHE)
+#define ENABLE_GEOLOCATION_PERMISSION_CACHE 0
+#endif
+
 #if !defined(ENABLE_INSPECTOR)
 #define ENABLE_INSPECTOR 1
 #endif
 #if !defined(ENABLE_INSPECTOR)
 #define ENABLE_INSPECTOR 1
 #endif
 #define ENABLE_GEOLOCATION 0
 #endif
 
 #define ENABLE_GEOLOCATION 0
 #endif
 
+#if !defined(ENABLE_NOTIFICATIONS)
+#define ENABLE_NOTIFICATIONS 0
+#endif
+
+#define ENABLE_TEXT_CARET 0
+
 #if !defined(ENABLE_TEXT_CARET)
 #define ENABLE_TEXT_CARET 1
 #endif
 #if !defined(ENABLE_TEXT_CARET)
 #define ENABLE_TEXT_CARET 1
 #endif
 #endif
 
 #if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64)
 #endif
 
 #if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64)
-#if PLATFORM(X86_64) && PLATFORM(MAC)
+#if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS))) || CPU(IA64) || CPU(ALPHA)
 #define WTF_USE_JSVALUE64 1
 #define WTF_USE_JSVALUE64 1
-#elif PLATFORM(PPC64) || PLATFORM(QT) || (PLATFORM(IPHONE) && PLATFORM_ARM_ARCH(6) && !defined(__llvm__))
-// FIXME: <rdar://problem/7478149> gcc-4.2 compiler bug with USE(JSVALUE32_64) and armv6 target
+#elif CPU(ARM) && !PLATFORM(IPHONE) || CPU(PPC64) || (PLATFORM(IPHONE) && defined(WTF_ARM_ARCH_VERSION) && WTF_ARM_ARCH_VERSION == 6 && !defined(__llvm__))
+/* FIXME: <rdar://problem/7478149> gcc-4.2 compiler bug with USE(JSVALUE32_64) and armv6 target */
+#define WTF_USE_JSVALUE32 1
+#elif OS(WINDOWS) && COMPILER(MINGW)
+/* Using JSVALUE32_64 causes padding/alignement issues for JITStubArg
+on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
 #define WTF_USE_JSVALUE32 1
 #else
 #define WTF_USE_JSVALUE32_64 1
 #endif
 #define WTF_USE_JSVALUE32 1
 #else
 #define WTF_USE_JSVALUE32_64 1
 #endif
-#endif // !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64)
+#endif /* !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64) */
 
 #if !defined(ENABLE_REPAINT_THROTTLING)
 #define ENABLE_REPAINT_THROTTLING 0
 #endif
 
 #if !defined(ENABLE_JIT)
 
 #if !defined(ENABLE_REPAINT_THROTTLING)
 #define ENABLE_REPAINT_THROTTLING 0
 #endif
 
 #if !defined(ENABLE_JIT)
+
 /* The JIT is tested & working on x86_64 Mac */
 /* The JIT is tested & working on x86_64 Mac */
-#if PLATFORM(X86_64) && PLATFORM(MAC)
+#if CPU(X86_64) && PLATFORM(MAC)
     #define ENABLE_JIT 1
 /* The JIT is tested & working on x86 Mac */
     #define ENABLE_JIT 1
 /* The JIT is tested & working on x86 Mac */
-#elif PLATFORM(X86) && PLATFORM(MAC)
+#elif CPU(X86) && PLATFORM(MAC)
     #define ENABLE_JIT 1
     #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
     #define ENABLE_JIT 1
     #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
-#elif PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE)
-    /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */
-    #define ENABLE_JIT 0
-    #define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 0
+#elif CPU(ARM_THUMB2) && PLATFORM(IPHONE)
+    #define ENABLE_JIT 1
 /* The JIT is tested & working on x86 Windows */
 /* The JIT is tested & working on x86 Windows */
-#elif PLATFORM(X86) && PLATFORM(WIN)
+#elif CPU(X86) && PLATFORM(WIN)
     #define ENABLE_JIT 1
 #endif
     #define ENABLE_JIT 1
 #endif
+
+#if PLATFORM(QT)
+#if CPU(X86_64) && OS(DARWIN)
+    #define ENABLE_JIT 1
+#elif CPU(X86) && OS(DARWIN)
+    #define ENABLE_JIT 1
+    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
+#elif CPU(X86) && OS(WINDOWS) && COMPILER(MINGW) && GCC_VERSION >= 40100
+    #define ENABLE_JIT 1
+    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
+#elif CPU(X86) && OS(WINDOWS) && COMPILER(MSVC)
+    #define ENABLE_JIT 1
+    #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1
+#elif CPU(X86) && OS(LINUX) && GCC_VERSION >= 40100
+    #define ENABLE_JIT 1
+    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
+#elif CPU(X86_64) && OS(LINUX) && GCC_VERSION >= 40100
+    #define ENABLE_JIT 1
+#elif CPU(ARM_TRADITIONAL) && OS(LINUX)
+    #define ENABLE_JIT 1
 #endif
 #endif
+#endif /* PLATFORM(QT) */
+
+#endif /* !defined(ENABLE_JIT) */
 
 #if ENABLE(JIT)
 #ifndef ENABLE_JIT_OPTIMIZE_CALL
 
 #if ENABLE(JIT)
 #ifndef ENABLE_JIT_OPTIMIZE_CALL
 #endif
 #endif
 
 #endif
 #endif
 
-#if PLATFORM(X86) && COMPILER(MSVC)
+#if CPU(X86) && COMPILER(MSVC)
 #define JSC_HOST_CALL __fastcall
 #define JSC_HOST_CALL __fastcall
-#elif PLATFORM(X86) && COMPILER(GCC)
+#elif CPU(X86) && COMPILER(GCC)
 #define JSC_HOST_CALL __attribute__ ((fastcall))
 #else
 #define JSC_HOST_CALL
 #define JSC_HOST_CALL __attribute__ ((fastcall))
 #else
 #define JSC_HOST_CALL
 #endif
 
 /* Yet Another Regex Runtime. */
 #endif
 
 /* Yet Another Regex Runtime. */
+#if !defined(ENABLE_YARR_JIT)
+
 /* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */
 /* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */
-#if (!defined(ENABLE_YARR_JIT) && PLATFORM(X86) && PLATFORM(MAC)) \
- || (!defined(ENABLE_YARR_JIT) && PLATFORM(X86_64) && PLATFORM(MAC)) \
- /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ \
- || (!defined(ENABLE_YARR_JIT) && PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE) && 0) \
- || (!defined(ENABLE_YARR_JIT) && PLATFORM(X86) && PLATFORM(WIN))
+#if (CPU(X86) && PLATFORM(MAC)) \
+    || (CPU(X86_64) && PLATFORM(MAC)) \
+    || (CPU(ARM_THUMB2) && PLATFORM(IPHONE)) \
+    || (CPU(X86) && PLATFORM(WIN))
+#define ENABLE_YARR 1
+#define ENABLE_YARR_JIT 1
+#endif
+
+#if PLATFORM(QT)
+#if (CPU(X86) && OS(WINDOWS) && COMPILER(MINGW) && GCC_VERSION >= 40100) \
+    || (CPU(X86) && OS(WINDOWS) && COMPILER(MSVC)) \
+    || (CPU(X86) && OS(LINUX) && GCC_VERSION >= 40100) \
+    || (CPU(X86_64) && OS(LINUX) && GCC_VERSION >= 40100) \
+    || (CPU(ARM_TRADITIONAL) && OS(LINUX))
 #define ENABLE_YARR 1
 #define ENABLE_YARR_JIT 1
 #endif
 #define ENABLE_YARR 1
 #define ENABLE_YARR_JIT 1
 #endif
+#endif
+
+#endif /* !defined(ENABLE_YARR_JIT) */
+
 /* Sanity Check */
 #if ENABLE(YARR_JIT) && !ENABLE(YARR)
 #error "YARR_JIT requires YARR"
 /* Sanity Check */
 #if ENABLE(YARR_JIT) && !ENABLE(YARR)
 #error "YARR_JIT requires YARR"
 #endif
 /* Setting this flag prevents the assembler from using RWX memory; this may improve
    security but currectly comes at a significant performance cost. */
 #endif
 /* Setting this flag prevents the assembler from using RWX memory; this may improve
    security but currectly comes at a significant performance cost. */
-#if PLATFORM_ARM_ARCH(7) && PLATFORM(IPHONE)
 #define ENABLE_ASSEMBLER_WX_EXCLUSIVE 1
 #define ENABLE_ASSEMBLER_WX_EXCLUSIVE 1
-#else
-#define ENABLE_ASSEMBLER_WX_EXCLUSIVE 0
-#endif
 
 
-#if !defined(ENABLE_PAN_SCROLLING) && PLATFORM(WIN_OS)
+#if !defined(ENABLE_PAN_SCROLLING) && OS(WINDOWS)
 #define ENABLE_PAN_SCROLLING 1
 #endif
 
 #define ENABLE_PAN_SCROLLING 1
 #endif
 
-#if !defined(ENABLE_ACTIVEX_TYPE_CONVERSION_WMPLAYER)
-#define ENABLE_ACTIVEX_TYPE_CONVERSION_WMPLAYER 1
-#endif
-
-/* Use the QtXmlStreamReader implementation for XMLTokenizer */
+/* Use the QXmlStreamReader implementation for XMLTokenizer */
+/* Use the QXmlQuery implementation for XSLTProcessor */
 #if PLATFORM(QT)
 #if PLATFORM(QT)
-#if !ENABLE(XSLT)
 #define WTF_USE_QXMLSTREAM 1
 #define WTF_USE_QXMLSTREAM 1
-#endif
+#define WTF_USE_QXMLQUERY 1
 #endif
 
 #if !PLATFORM(QT)
 #endif
 
 #if !PLATFORM(QT)
 
 /* Accelerated compositing */
 #if PLATFORM(MAC)
 
 /* Accelerated compositing */
 #if PLATFORM(MAC)
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#if !defined(BUILDING_ON_TIGER)
 #define WTF_USE_ACCELERATED_COMPOSITING 1
 #endif
 #endif
 
 #define WTF_USE_ACCELERATED_COMPOSITING 1
 
 #define WTF_USE_ACCELERATED_COMPOSITING 1
 #endif
 #endif
 
 #define WTF_USE_ACCELERATED_COMPOSITING 1
 
+/* FIXME: Defining ENABLE_3D_RENDERING here isn't really right, but it's always used with
+   with WTF_USE_ACCELERATED_COMPOSITING, and it allows the feature to be turned on and
+   off in one place. */
+#if PLATFORM(WIN)
+#include "QuartzCorePresent.h"
+#if QUARTZCORE_PRESENT
+#define WTF_USE_ACCELERATED_COMPOSITING 1
+#define ENABLE_3D_RENDERING 1
+#endif
+#endif
+
+#if COMPILER(GCC)
+#define WARN_UNUSED_RETURN __attribute__ ((warn_unused_result))
+#else
+#define WARN_UNUSED_RETURN
+#endif
+
+#if !ENABLE(NETSCAPE_PLUGIN_API) || (ENABLE(NETSCAPE_PLUGIN_API) && ((OS(UNIX) && (PLATFORM(QT) || PLATFORM(WX))) || PLATFORM(GTK)))
+#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 1
+#endif
+
+/* Set up a define for a common error that is intended to cause a build error -- thus the space after Error. */
+#define WTF_PLATFORM_CFNETWORK Error USE_macro_should_be_used_with_CFNETWORK
+
+#define ENABLE_JSC_ZOMBIES 0
+
 #endif /* WTF_Platform_h */
 #endif /* WTF_Platform_h */
diff --git a/wtf/PossiblyNull.h b/wtf/PossiblyNull.h
new file mode 100644 (file)
index 0000000..79c4d82
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PossiblyNull_h
+#define PossiblyNull_h
+
+#include "Assertions.h"
+
+namespace WTF {
+
+template <typename T> struct PossiblyNull {
+    PossiblyNull(T data)
+        : m_data(data)
+    {
+    }
+    PossiblyNull(const PossiblyNull<T>& source)
+        : m_data(source.m_data)
+    {
+        source.m_data = 0;
+    }
+    ~PossiblyNull() { ASSERT(!m_data); }
+    bool getValue(T& out) WARN_UNUSED_RETURN;
+private:
+    mutable T m_data;
+};
+
+template <typename T> bool PossiblyNull<T>::getValue(T& out)
+{
+    out = m_data;
+    bool result = !!m_data;
+    m_data = 0;
+    return result;
+}
+
+}
+
+#endif
index f4527df7411bf09fd2a80046a506cfa6d80a66f8..1e1bee044c731493042c19167ceddd7c41df5084 100644 (file)
 #include <wtf/Assertions.h>
 
 namespace WTF {
 #include <wtf/Assertions.h>
 
 namespace WTF {
-    template<class T, typename FlagEnum> class PtrAndFlags {
+    template<class T, typename FlagEnum> class PtrAndFlagsBase {
     public:
     public:
-        PtrAndFlags() : m_ptrAndFlags(0) {}
-
         bool isFlagSet(FlagEnum flagNumber) const { ASSERT(flagNumber < 2); return m_ptrAndFlags & (1 << flagNumber); }
         void setFlag(FlagEnum flagNumber) { ASSERT(flagNumber < 2); m_ptrAndFlags |= (1 << flagNumber);}
         void clearFlag(FlagEnum flagNumber) { ASSERT(flagNumber < 2); m_ptrAndFlags &= ~(1 << flagNumber);}
         bool isFlagSet(FlagEnum flagNumber) const { ASSERT(flagNumber < 2); return m_ptrAndFlags & (1 << flagNumber); }
         void setFlag(FlagEnum flagNumber) { ASSERT(flagNumber < 2); m_ptrAndFlags |= (1 << flagNumber);}
         void clearFlag(FlagEnum flagNumber) { ASSERT(flagNumber < 2); m_ptrAndFlags &= ~(1 << flagNumber);}
@@ -51,14 +49,31 @@ namespace WTF {
 #endif
         }
 
 #endif
         }
 
-    private:
+        bool operator!() const { return !get(); }
+        T* operator->() const { return reinterpret_cast<T*>(m_ptrAndFlags & ~3); }
+
+    protected:
         intptr_t m_ptrAndFlags;
 #ifndef NDEBUG
         void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced.
 #endif
     };
         intptr_t m_ptrAndFlags;
 #ifndef NDEBUG
         void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced.
 #endif
     };
+
+    template<class T, typename FlagEnum> class PtrAndFlags : public PtrAndFlagsBase<T, FlagEnum> {
+    public:
+        PtrAndFlags()
+        {
+            PtrAndFlagsBase<T, FlagEnum>::m_ptrAndFlags = 0;
+        }
+        PtrAndFlags(T* ptr)
+        {
+            PtrAndFlagsBase<T, FlagEnum>::m_ptrAndFlags = 0;
+            PtrAndFlagsBase<T, FlagEnum>::set(ptr);
+        }
+    };
 } // namespace WTF
 
 } // namespace WTF
 
+using WTF::PtrAndFlagsBase;
 using WTF::PtrAndFlags;
 
 #endif // PtrAndFlags_h
 using WTF::PtrAndFlags;
 
 #endif // PtrAndFlags_h
index c94d5a4b900d697197d688bd34ad24108399ea66..fc4826307a13c45549864d8ee22d67aa95658cb5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
 /*
  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *           (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include <stdint.h>
 #include <stdlib.h>
 
 #include <stdint.h>
 #include <stdlib.h>
 
+#if OS(WINCE)
+extern "C" {
+#include "wince/mt19937ar.c"
+}
+#endif
+
+#if PLATFORM(BREWMP)
+#include <AEEAppGen.h>
+#include <AEESource.h>
+#include <AEEStdLib.h>
+#endif
+
 namespace WTF {
 
 double weakRandomNumber()
 namespace WTF {
 
 double weakRandomNumber()
@@ -41,6 +53,10 @@ double weakRandomNumber()
 #if COMPILER(MSVC) && defined(_CRT_RAND_S)
     // rand_s is incredibly slow on windows so we fall back on rand for Math.random
     return (rand() + (rand() / (RAND_MAX + 1.0))) / (RAND_MAX + 1.0);
 #if COMPILER(MSVC) && defined(_CRT_RAND_S)
     // rand_s is incredibly slow on windows so we fall back on rand for Math.random
     return (rand() + (rand() / (RAND_MAX + 1.0))) / (RAND_MAX + 1.0);
+#elif PLATFORM(BREWMP)
+    uint32_t bits;
+    GETRAND(reinterpret_cast<byte*>(&bits), sizeof(uint32_t));
+    return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
 #else
     return randomNumber();
 #endif
 #else
     return randomNumber();
 #endif
@@ -60,10 +76,10 @@ double randomNumber()
     uint32_t bits;
     rand_s(&bits);
     return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
     uint32_t bits;
     rand_s(&bits);
     return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
-#elif PLATFORM(DARWIN)
+#elif OS(DARWIN)
     uint32_t bits = arc4random();
     return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
     uint32_t bits = arc4random();
     return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
-#elif PLATFORM(UNIX)
+#elif OS(UNIX)
     uint32_t part1 = random() & (RAND_MAX - 1);
     uint32_t part2 = random() & (RAND_MAX - 1);
     // random only provides 31 bits
     uint32_t part1 = random() & (RAND_MAX - 1);
     uint32_t part2 = random() & (RAND_MAX - 1);
     // random only provides 31 bits
@@ -74,6 +90,35 @@ double randomNumber()
     // Mask off the low 53bits
     fullRandom &= (1LL << 53) - 1;
     return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
     // Mask off the low 53bits
     fullRandom &= (1LL << 53) - 1;
     return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
+#elif OS(WINCE)
+    return genrand_res53();
+#elif OS(WINDOWS)
+    uint32_t part1 = rand() & (RAND_MAX - 1);
+    uint32_t part2 = rand() & (RAND_MAX - 1);
+    uint32_t part3 = rand() & (RAND_MAX - 1);
+    uint32_t part4 = rand() & (RAND_MAX - 1);
+    // rand only provides 15 bits on Win32
+    uint64_t fullRandom = part1;
+    fullRandom <<= 15;
+    fullRandom |= part2;
+    fullRandom <<= 15;
+    fullRandom |= part3;
+    fullRandom <<= 15;
+    fullRandom |= part4;
+
+    // Mask off the low 53bits
+    fullRandom &= (1LL << 53) - 1;
+    return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
+#elif PLATFORM(BREWMP)
+    uint32_t bits;
+    ISource* randomSource;
+
+    IShell* shell = reinterpret_cast<AEEApplet*>(GETAPPINSTANCE())->m_pIShell;
+    ISHELL_CreateInstance(shell, AEECLSID_RANDOM, reinterpret_cast<void**>(&randomSource));
+    ISOURCE_Read(randomSource, reinterpret_cast<char*>(&bits), 4);
+    ISOURCE_Release(randomSource);
+
+    return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
 #else
     uint32_t part1 = rand() & (RAND_MAX - 1);
     uint32_t part2 = rand() & (RAND_MAX - 1);
 #else
     uint32_t part1 = rand() & (RAND_MAX - 1);
     uint32_t part2 = rand() & (RAND_MAX - 1);
index f994fd9e35c50e0d89d37c2ba691df08495510d5..ae414c0e32a7f5f395138935fe26f496c9039613 100644 (file)
 #include <sys/time.h>
 #endif
 
 #include <sys/time.h>
 #endif
 
-#if PLATFORM(UNIX)
+#if OS(UNIX)
 #include <sys/types.h>
 #include <unistd.h>
 #endif
 
 #include <sys/types.h>
 #include <unistd.h>
 #endif
 
+#if OS(WINCE)
+extern "C" {
+void init_by_array(unsigned long init_key[],int key_length);
+}
+#endif
+
 // Internal JavaScriptCore usage only
 namespace WTF {
 
 inline void initializeRandomNumberGenerator()
 {
 // Internal JavaScriptCore usage only
 namespace WTF {
 
 inline void initializeRandomNumberGenerator()
 {
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
     // On Darwin we use arc4random which initialises itself.
     // On Darwin we use arc4random which initialises itself.
+#elif OS(WINCE)
+    // initialize rand()
+    srand(static_cast<unsigned>(time(0)));
+
+    // use rand() to initialize the real RNG
+    unsigned long initializationBuffer[4];
+    initializationBuffer[0] = (rand() << 16) | rand();
+    initializationBuffer[1] = (rand() << 16) | rand();
+    initializationBuffer[2] = (rand() << 16) | rand();
+    initializationBuffer[3] = (rand() << 16) | rand();
+    init_by_array(initializationBuffer, 4);
 #elif COMPILER(MSVC) && defined(_CRT_RAND_S)
 #elif COMPILER(MSVC) && defined(_CRT_RAND_S)
-    // On Windows we use rand_s which intialises itself
-#elif PLATFORM(UNIX)
+    // On Windows we use rand_s which initialises itself
+#elif OS(UNIX)
     // srandomdev is not guaranteed to exist on linux so we use this poor seed, this should be improved
     timeval time;
     gettimeofday(&time, 0);
     // srandomdev is not guaranteed to exist on linux so we use this poor seed, this should be improved
     timeval time;
     gettimeofday(&time, 0);
index c174145dceebff3cc11bc91bb8096abc6cebb803..761a8566f4fcb777c8b9f114c83a128f28f424e6 100644 (file)
@@ -29,7 +29,7 @@ namespace WTF {
 // This base class holds the non-template methods and attributes.
 // The RefCounted class inherits from it reducing the template bloat
 // generated by the compiler (technique called template hoisting).
 // This base class holds the non-template methods and attributes.
 // The RefCounted class inherits from it reducing the template bloat
 // generated by the compiler (technique called template hoisting).
-class RefCountedBase : Noncopyable {
+class RefCountedBase {
 public:
     void ref()
     {
 public:
     void ref()
     {
@@ -101,7 +101,7 @@ private:
 };
 
 
 };
 
 
-template<class T> class RefCounted : public RefCountedBase {
+template<class T> class RefCounted : public RefCountedBase, public Noncopyable {
 public:
     void deref()
     {
 public:
     void deref()
     {
@@ -115,8 +115,23 @@ protected:
     }
 };
 
     }
 };
 
+template<class T> class RefCountedCustomAllocated : public RefCountedBase, public NoncopyableCustomAllocated {
+public:
+    void deref()
+    {
+        if (derefBase())
+            delete static_cast<T*>(this);
+    }
+
+protected:
+    ~RefCountedCustomAllocated()
+    {
+    }
+};
+
 } // namespace WTF
 
 using WTF::RefCounted;
 } // namespace WTF
 
 using WTF::RefCounted;
+using WTF::RefCountedCustomAllocated;
 
 #endif // RefCounted_h
 
 #endif // RefCounted_h
index 74cd0ead4b6d6966e71c0de7402fdb73e6041319..e6d10477c06366725922aa9ece51cc5f435c1d5d 100644 (file)
@@ -30,6 +30,7 @@ namespace WTF {
     enum PlacementNewAdoptType { PlacementNewAdopt };
 
     template <typename T> class PassRefPtr;
     enum PlacementNewAdoptType { PlacementNewAdopt };
 
     template <typename T> class PassRefPtr;
+    template <typename T> class NonNullPassRefPtr;
 
     enum HashTableDeletedValueType { HashTableDeletedValue };
 
 
     enum HashTableDeletedValueType { HashTableDeletedValue };
 
@@ -40,6 +41,7 @@ namespace WTF {
         RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { if (T* ptr = m_ptr) ptr->ref(); }
         // see comment in PassRefPtr.h for why this takes const reference
         template <typename U> RefPtr(const PassRefPtr<U>&);
         RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { if (T* ptr = m_ptr) ptr->ref(); }
         // see comment in PassRefPtr.h for why this takes const reference
         template <typename U> RefPtr(const PassRefPtr<U>&);
+        template <typename U> RefPtr(const NonNullPassRefPtr<U>&);
 
         // Special constructor for cases where we overwrite an object in place.
         RefPtr(PlacementNewAdoptType) { }
 
         // Special constructor for cases where we overwrite an object in place.
         RefPtr(PlacementNewAdoptType) { }
@@ -73,8 +75,10 @@ namespace WTF {
         RefPtr& operator=(const RefPtr&);
         RefPtr& operator=(T*);
         RefPtr& operator=(const PassRefPtr<T>&);
         RefPtr& operator=(const RefPtr&);
         RefPtr& operator=(T*);
         RefPtr& operator=(const PassRefPtr<T>&);
+        RefPtr& operator=(const NonNullPassRefPtr<T>&);
         template <typename U> RefPtr& operator=(const RefPtr<U>&);
         template <typename U> RefPtr& operator=(const PassRefPtr<U>&);
         template <typename U> RefPtr& operator=(const RefPtr<U>&);
         template <typename U> RefPtr& operator=(const PassRefPtr<U>&);
+        template <typename U> RefPtr& operator=(const NonNullPassRefPtr<U>&);
 
         void swap(RefPtr&);
 
 
         void swap(RefPtr&);
 
@@ -89,6 +93,11 @@ namespace WTF {
     {
     }
 
     {
     }
 
+    template <typename T> template <typename U> inline RefPtr<T>::RefPtr(const NonNullPassRefPtr<U>& o)
+        : m_ptr(o.releaseRef())
+    {
+    }
+
     template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o)
     {
         T* optr = o.get();
     template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o)
     {
         T* optr = o.get();
@@ -133,6 +142,15 @@ namespace WTF {
         return *this;
     }
 
         return *this;
     }
 
+    template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<T>& o)
+    {
+        T* ptr = m_ptr;
+        m_ptr = o.releaseRef();
+        if (ptr)
+            ptr->deref();
+        return *this;
+    }
+
     template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o)
     {
         T* ptr = m_ptr;
     template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o)
     {
         T* ptr = m_ptr;
@@ -142,6 +160,15 @@ namespace WTF {
         return *this;
     }
 
         return *this;
     }
 
+    template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<U>& o)
+    {
+        T* ptr = m_ptr;
+        m_ptr = o.releaseRef();
+        if (ptr)
+            ptr->deref();
+        return *this;
+    }
+
     template <class T> inline void RefPtr<T>::swap(RefPtr<T>& o)
     {
         std::swap(m_ptr, o.m_ptr);
     template <class T> inline void RefPtr<T>::swap(RefPtr<T>& o)
     {
         std::swap(m_ptr, o.m_ptr);
index 1cbebb4fe369c046b3d8c5a77e2ba886000401f1..7f6ebfeaddae442097f3d692cf72203e5decbbe9 100644 (file)
@@ -42,7 +42,7 @@ namespace WTF {
     };
 
     template<typename T, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
     };
 
     template<typename T, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
-    class HashMap<RefPtr<T>, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> {
+    class HashMap<RefPtr<T>, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> : public FastAllocBase {
     private:
         typedef KeyTraitsArg KeyTraits;
         typedef MappedTraitsArg MappedTraits;
     private:
         typedef KeyTraitsArg KeyTraits;
         typedef MappedTraitsArg MappedTraits;
@@ -285,7 +285,7 @@ namespace WTF {
     {
         if (it.m_impl == m_impl.end())
             return;
     {
         if (it.m_impl == m_impl.end())
             return;
-        m_impl.checkTableConsistency();
+        m_impl.internalCheckTableConsistency();
         m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
     }
 
         m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
     }
 
index 065c19ccece10bc36fb096b99a251913a14bf4f4..b1cbc4dcff082c969fc3d8ecc9ba1407374e0606 100644 (file)
@@ -116,6 +116,7 @@ namespace WTF {
         }
 
         size_t size() const { return m_size; }
         }
 
         size_t size() const { return m_size; }
+        bool isEmpty() const { return !size(); }
 
         T& at(size_t index)
         {
 
         T& at(size_t index)
         {
@@ -249,4 +250,6 @@ namespace WTF {
 
 } // namespace WTF
 
 
 } // namespace WTF
 
+using WTF::SegmentedVector;
+
 #endif // SegmentedVector_h
 #endif // SegmentedVector_h
index d21d1ffccf8b61a5c8da7f77f4f81346ed1d530b..9dfb9699725aae558e2e70f76c241546bb1c7e37 100644 (file)
@@ -32,6 +32,7 @@
 // Use these to declare and define a static local variable (static T;) so that
 //  it is leaked so that its destructors are not called at exit. Using this
 //  macro also allows workarounds a compiler bug present in Apple's version of GCC 4.0.1.
 // Use these to declare and define a static local variable (static T;) so that
 //  it is leaked so that its destructors are not called at exit. Using this
 //  macro also allows workarounds a compiler bug present in Apple's version of GCC 4.0.1.
+#ifndef DEFINE_STATIC_LOCAL
 #if COMPILER(GCC) && defined(__APPLE_CC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 1
 #define DEFINE_STATIC_LOCAL(type, name, arguments) \
     static type* name##Ptr = new type arguments; \
 #if COMPILER(GCC) && defined(__APPLE_CC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 1
 #define DEFINE_STATIC_LOCAL(type, name, arguments) \
     static type* name##Ptr = new type arguments; \
 #define DEFINE_STATIC_LOCAL(type, name, arguments) \
     static type& name = *new type arguments
 #endif
 #define DEFINE_STATIC_LOCAL(type, name, arguments) \
     static type& name = *new type arguments
 #endif
+#endif
 
 // OBJECT_OFFSETOF: Like the C++ offsetof macro, but you can use it with classes.
 // The magic number 0x4000 is insignificant. We use it to avoid using NULL, since
 // NULL can cause compiler problems, especially in cases of multiple inheritance.
 #define OBJECT_OFFSETOF(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)
 
 
 // OBJECT_OFFSETOF: Like the C++ offsetof macro, but you can use it with classes.
 // The magic number 0x4000 is insignificant. We use it to avoid using NULL, since
 // NULL can cause compiler problems, especially in cases of multiple inheritance.
 #define OBJECT_OFFSETOF(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)
 
+// STRINGIZE: Can convert any value to quoted string, even expandable macros
+#define STRINGIZE(exp) #exp
+#define STRINGIZE_VALUE_OF(exp) STRINGIZE(exp)
+
 namespace WTF {
 
     /*
 namespace WTF {
 
     /*
@@ -63,6 +69,14 @@ namespace WTF {
         return u.to;
     }
 
         return u.to;
     }
 
+    // Returns a count of the number of bits set in 'bits'.
+    inline size_t bitCount(unsigned bits)
+    {
+        bits = bits - ((bits >> 1) & 0x55555555);
+        bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
+        return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
+    }
+
 } // namespace WTF
 
 #endif
 } // namespace WTF
 
 #endif
diff --git a/wtf/StringExtras.cpp b/wtf/StringExtras.cpp
new file mode 100644 (file)
index 0000000..1b96417
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+
+#if COMPILER(RVCT) && __ARMCC_VERSION < 400000
+
+#include "StringExtras.h"
+
+#include "ASCIICType.h"
+
+int strcasecmp(const char* s1, const char* s2)
+{
+    while (toASCIIUpper(*s1) == toASCIIUpper(*s2)) {
+        if (*s1 == '\0')
+            return 0;
+        s1++;
+        s2++;
+    }
+
+    return toASCIIUpper(*s1) - toASCIIUpper(*s2);
+}
+
+int strncasecmp(const char* s1, const char* s2, size_t len)
+{
+    while (len > 0 && toASCIIUpper(*s1) == toASCIIUpper(*s2)) {
+        if (*s1 == '\0')
+            return 0;
+        s1++;
+        s2++;
+        len--;
+    }
+
+    if (!len)
+        return 0;
+
+    return toASCIIUpper(*s1) - toASCIIUpper(*s2);
+}
+
+#endif
index 1c23390d55617b1fa8da7d6870b52c673f8d43e6..b1ec09f095ce570de85cd5f1b40aa6d1b7334fef 100644 (file)
@@ -34,6 +34,7 @@
 #endif 
 
 #if COMPILER(MSVC)
 #endif 
 
 #if COMPILER(MSVC)
+// FIXME: why a COMPILER check instead of OS? also, these should be HAVE checks
 
 inline int snprintf(char* buffer, size_t count, const char* format, ...) 
 {
 
 inline int snprintf(char* buffer, size_t count, const char* format, ...) 
 {
@@ -45,7 +46,7 @@ inline int snprintf(char* buffer, size_t count, const char* format, ...)
     return result;
 }
 
     return result;
 }
 
-#if COMPILER(MSVC7) || PLATFORM(WINCE)
+#if COMPILER(MSVC7) || OS(WINCE)
 
 inline int vsnprintf(char* buffer, size_t count, const char* format, va_list args)
 {
 
 inline int vsnprintf(char* buffer, size_t count, const char* format, va_list args)
 {
@@ -54,7 +55,7 @@ inline int vsnprintf(char* buffer, size_t count, const char* format, va_list arg
 
 #endif
 
 
 #endif
 
-#if PLATFORM(WINCE)
+#if OS(WINCE)
 
 inline int strnicmp(const char* string1, const char* string2, size_t count)
 {
 
 inline int strnicmp(const char* string1, const char* string2, size_t count)
 {
@@ -75,14 +76,38 @@ inline char* strdup(const char* strSource)
 
 inline int strncasecmp(const char* s1, const char* s2, size_t len)
 {
 
 inline int strncasecmp(const char* s1, const char* s2, size_t len)
 {
-    return strnicmp(s1, s2, len);
+    return _strnicmp(s1, s2, len);
 }
 
 inline int strcasecmp(const char* s1, const char* s2)
 {
 }
 
 inline int strcasecmp(const char* s1, const char* s2)
 {
-    return stricmp(s1, s2);
+    return _stricmp(s1, s2);
 }
 
 #endif
 
 }
 
 #endif
 
+#if OS(WINDOWS) || OS(LINUX) || OS(SOLARIS)
+// FIXME: should check HAVE_STRNSTR
+
+inline char* strnstr(const char* buffer, const char* target, size_t bufferLength)
+{
+    size_t targetLength = strlen(target);
+    if (targetLength == 0)
+        return const_cast<char*>(buffer);
+    for (const char* start = buffer; *start && start + targetLength <= buffer + bufferLength; start++) {
+        if (*start == *target && strncmp(start + 1, target + 1, targetLength - 1) == 0)
+            return const_cast<char*>(start);
+    }
+    return 0;
+}
+
+#endif
+
+#if COMPILER(RVCT) && __ARMCC_VERSION < 400000
+
+int strcasecmp(const char* s1, const char* s2);
+int strncasecmp(const char* s1, const char* s2, size_t len);
+
+#endif
+
 #endif // WTF_StringExtras_h
 #endif // WTF_StringExtras_h
diff --git a/wtf/StringHashFunctions.h b/wtf/StringHashFunctions.h
new file mode 100644 (file)
index 0000000..07f117f
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2005, 2006, 2008, 2010 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef WTF_StringHashFunctions_h
+#define WTF_StringHashFunctions_h
+
+#include <wtf/unicode/Unicode.h>
+
+namespace WTF {
+
+// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
+static const unsigned stringHashingStartValue = 0x9e3779b9U;
+
+// stringHash methods based on Paul Hsieh's SuperFastHash.
+// http://www.azillionmonkeys.com/qed/hash.html
+// char* data is interpreted as latin-encoded (zero extended to 16 bits).
+
+inline unsigned stringHash(const UChar* data, unsigned length)
+{
+    unsigned hash = WTF::stringHashingStartValue;
+    unsigned rem = length & 1;
+    length >>= 1;
+
+    // Main loop
+    for (; length > 0; length--) {
+        hash += data[0];
+        unsigned tmp = (data[1] << 11) ^ hash;
+        hash = (hash << 16) ^ tmp;
+        data += 2;
+        hash += hash >> 11;
+    }
+
+    // Handle end case
+    if (rem) {
+        hash += data[0];
+        hash ^= hash << 11;
+        hash += hash >> 17;
+    }
+
+    // Force "avalanching" of final 127 bits
+    hash ^= hash << 3;
+    hash += hash >> 5;
+    hash ^= hash << 2;
+    hash += hash >> 15;
+    hash ^= hash << 10;
+
+    hash &= 0x7fffffff;
+
+    // this avoids ever returning a hash code of 0, since that is used to
+    // signal "hash not computed yet", using a value that is likely to be
+    // effectively the same as 0 when the low bits are masked
+    if (hash == 0)
+        hash = 0x40000000;
+
+    return hash;
+}
+
+inline unsigned stringHash(const char* data, unsigned length)
+{
+    unsigned hash = WTF::stringHashingStartValue;
+    unsigned rem = length & 1;
+    length >>= 1;
+
+    // Main loop
+    for (; length > 0; length--) {
+        hash += static_cast<unsigned char>(data[0]);
+        unsigned tmp = (static_cast<unsigned char>(data[1]) << 11) ^ hash;
+        hash = (hash << 16) ^ tmp;
+        data += 2;
+        hash += hash >> 11;
+    }
+
+    // Handle end case
+    if (rem) {
+        hash += static_cast<unsigned char>(data[0]);
+        hash ^= hash << 11;
+        hash += hash >> 17;
+    }
+
+    // Force "avalanching" of final 127 bits
+    hash ^= hash << 3;
+    hash += hash >> 5;
+    hash ^= hash << 2;
+    hash += hash >> 15;
+    hash ^= hash << 10;
+
+    hash &= 0x7fffffff;
+
+    // this avoids ever returning a hash code of 0, since that is used to
+    // signal "hash not computed yet", using a value that is likely to be
+    // effectively the same as 0 when the low bits are masked
+    if (hash == 0)
+        hash = 0x40000000;
+
+    return hash;
+}
+
+inline unsigned stringHash(const char* data)
+{
+    unsigned hash = WTF::stringHashingStartValue;
+
+    // Main loop
+    for (;;) {
+        unsigned char b0 = data[0];
+        if (!b0)
+            break;
+        unsigned char b1 = data[1];
+        if (!b1) {
+            hash += b0;
+            hash ^= hash << 11;
+            hash += hash >> 17;
+            break;
+        }
+        hash += b0;
+        unsigned tmp = (b1 << 11) ^ hash;
+        hash = (hash << 16) ^ tmp;
+        data += 2;
+        hash += hash >> 11;
+    }
+
+    // Force "avalanching" of final 127 bits.
+    hash ^= hash << 3;
+    hash += hash >> 5;
+    hash ^= hash << 2;
+    hash += hash >> 15;
+    hash ^= hash << 10;
+
+    hash &= 0x7fffffff;
+
+    // This avoids ever returning a hash code of 0, since that is used to
+    // signal "hash not computed yet", using a value that is likely to be
+    // effectively the same as 0 when the low bits are masked.
+    if (hash == 0)
+        hash = 0x40000000;
+
+    return hash;
+}
+
+} // namespace WTF
+
+#endif // WTF_StringHashFunctions_h
index ced22834adc26ed524ab64ce194dd92511d87cb1..8a73e135fb7d03f279d396744eada6fbdb8f2918 100644 (file)
@@ -33,7 +33,7 @@
 #ifndef TCMALLOC_INTERNAL_SPINLOCK_H__
 #define TCMALLOC_INTERNAL_SPINLOCK_H__
 
 #ifndef TCMALLOC_INTERNAL_SPINLOCK_H__
 #define TCMALLOC_INTERNAL_SPINLOCK_H__
 
-#if (PLATFORM(X86) || PLATFORM(PPC)) && (COMPILER(GCC) || COMPILER(MSVC))
+#if (CPU(X86) || CPU(X86_64) || CPU(PPC)) && (COMPILER(GCC) || COMPILER(MSVC))
 
 #include <time.h>       /* For nanosleep() */
 
 
 #include <time.h>       /* For nanosleep() */
 
@@ -47,7 +47,7 @@
 #include <sys/types.h>
 #endif
 
 #include <sys/types.h>
 #endif
 
-#if PLATFORM(WIN_OS)
+#if OS(WINDOWS)
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #endif
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #endif
@@ -62,7 +62,7 @@ struct TCMalloc_SpinLock {
   inline void Lock() {
     int r;
 #if COMPILER(GCC)
   inline void Lock() {
     int r;
 #if COMPILER(GCC)
-#if PLATFORM(X86)
+#if CPU(X86) || CPU(X86_64)
     __asm__ __volatile__
       ("xchgl %0, %1"
        : "=r"(r), "=m"(lockword_)
     __asm__ __volatile__
       ("xchgl %0, %1"
        : "=r"(r), "=m"(lockword_)
@@ -92,7 +92,7 @@ struct TCMalloc_SpinLock {
 
   inline void Unlock() {
 #if COMPILER(GCC)
 
   inline void Unlock() {
 #if COMPILER(GCC)
-#if PLATFORM(X86)
+#if CPU(X86) || CPU(X86_64)
     __asm__ __volatile__
       ("movl $0, %0"
        : "=m"(lockword_)
     __asm__ __volatile__
       ("movl $0, %0"
        : "=m"(lockword_)
@@ -103,7 +103,7 @@ struct TCMalloc_SpinLock {
       ("isync\n\t"
        "eieio\n\t"
        "stw %1, %0"
       ("isync\n\t"
        "eieio\n\t"
        "stw %1, %0"
-#if PLATFORM(DARWIN) || PLATFORM(PPC)
+#if OS(DARWIN) || CPU(PPC)
        : "=o" (lockword_)
 #else
        : "=m" (lockword_) 
        : "=o" (lockword_)
 #else
        : "=m" (lockword_) 
@@ -138,7 +138,7 @@ static void TCMalloc_SlowLock(volatile unsigned int* lockword) {
   while (true) {
     int r;
 #if COMPILER(GCC)
   while (true) {
     int r;
 #if COMPILER(GCC)
-#if PLATFORM(X86)
+#if CPU(X86) || CPU(X86_64)
     __asm__ __volatile__
       ("xchgl %0, %1"
        : "=r"(r), "=m"(*lockword)
     __asm__ __volatile__
       ("xchgl %0, %1"
        : "=r"(r), "=m"(*lockword)
@@ -178,7 +178,7 @@ static void TCMalloc_SlowLock(volatile unsigned int* lockword) {
     // from taking 30 seconds to 16 seconds.
 
     // Sleep for a few milliseconds
     // from taking 30 seconds to 16 seconds.
 
     // Sleep for a few milliseconds
-#if PLATFORM(WIN_OS)
+#if OS(WINDOWS)
     Sleep(2);
 #else
     struct timespec tm;
     Sleep(2);
 #else
     struct timespec tm;
@@ -209,6 +209,13 @@ struct TCMalloc_SpinLock {
   inline void Unlock() {
     if (pthread_mutex_unlock(&private_lock_) != 0) CRASH();
   }
   inline void Unlock() {
     if (pthread_mutex_unlock(&private_lock_) != 0) CRASH();
   }
+  bool IsHeld() {
+    if (pthread_mutex_trylock(&private_lock_))
+      return true;
+
+    Unlock();
+    return false;
+  }
 };
 
 #define SPINLOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
 };
 
 #define SPINLOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
index 659bb0e64d9f47c4ff108919b994e110fdfe34e4..c46ff311f1cfd29bd11d1b5768de3908ae824d7f 100644 (file)
@@ -38,6 +38,7 @@
 #include "Assertions.h"
 #include "TCSpinLock.h"
 #include "UnusedParam.h"
 #include "Assertions.h"
 #include "TCSpinLock.h"
 #include "UnusedParam.h"
+#include "VMTags.h"
 
 #if HAVE(STDINT_H)
 #include <stdint.h>
 
 #if HAVE(STDINT_H)
 #include <stdint.h>
@@ -47,7 +48,7 @@
 #include <sys/types.h>
 #endif
 
 #include <sys/types.h>
 #endif
 
-#if PLATFORM(WIN_OS)
+#if OS(WINDOWS)
 #include "windows.h"
 #else
 #include <errno.h>
 #include "windows.h"
 #else
 #include <errno.h>
@@ -178,7 +179,7 @@ static void* TryMmap(size_t size, size_t *actual_size, size_t alignment) {
   void* result = mmap(NULL, size + extra,
                       PROT_READ | PROT_WRITE,
                       MAP_PRIVATE|MAP_ANONYMOUS,
   void* result = mmap(NULL, size + extra,
                       PROT_READ | PROT_WRITE,
                       MAP_PRIVATE|MAP_ANONYMOUS,
-                      -1, 0);
+                      VM_TAG_FOR_TCMALLOC_MEMORY, 0);
   if (result == reinterpret_cast<void*>(MAP_FAILED)) {
     mmap_failure = true;
     return NULL;
   if (result == reinterpret_cast<void*>(MAP_FAILED)) {
     mmap_failure = true;
     return NULL;
diff --git a/wtf/ThreadIdentifierDataPthreads.cpp b/wtf/ThreadIdentifierDataPthreads.cpp
new file mode 100644 (file)
index 0000000..042d49e
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(PTHREADS)
+
+#include "ThreadIdentifierDataPthreads.h"
+
+#include "Threading.h"
+
+namespace WTF {
+
+pthread_key_t ThreadIdentifierData::m_key;
+
+void clearPthreadHandleForIdentifier(ThreadIdentifier);
+
+ThreadIdentifierData::~ThreadIdentifierData()
+{
+    clearPthreadHandleForIdentifier(m_identifier);
+}
+
+ThreadIdentifier ThreadIdentifierData::identifier()
+{
+    initializeKeyOnce();
+    ThreadIdentifierData* threadIdentifierData = static_cast<ThreadIdentifierData*>(pthread_getspecific(m_key));
+
+    return threadIdentifierData ? threadIdentifierData->m_identifier : 0;
+}
+
+void ThreadIdentifierData::initialize(ThreadIdentifier id)
+{
+    ASSERT(!identifier());
+
+    initializeKeyOnce();
+    pthread_setspecific(m_key, new ThreadIdentifierData(id));
+}
+
+void ThreadIdentifierData::destruct(void* data)
+{
+    ThreadIdentifierData* threadIdentifierData = static_cast<ThreadIdentifierData*>(data);
+    ASSERT(threadIdentifierData);
+
+    if (threadIdentifierData->m_isDestroyedOnce) {
+        delete threadIdentifierData;
+        return;
+    }
+
+    threadIdentifierData->m_isDestroyedOnce = true;
+    // Re-setting the value for key causes another destruct() call after all other thread-specific destructors were called.
+    pthread_setspecific(m_key, threadIdentifierData);
+}
+
+void ThreadIdentifierData::initializeKeyOnceHelper()
+{
+    if (pthread_key_create(&m_key, destruct))
+        CRASH();
+}
+
+void ThreadIdentifierData::initializeKeyOnce()
+{
+    static pthread_once_t onceControl = PTHREAD_ONCE_INIT;
+    if (pthread_once(&onceControl, initializeKeyOnceHelper))
+        CRASH();
+}
+
+} // namespace WTF
+
+#endif // USE(PTHREADS)
+
diff --git a/wtf/ThreadIdentifierDataPthreads.h b/wtf/ThreadIdentifierDataPthreads.h
new file mode 100644 (file)
index 0000000..3af87a8
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ThreadIdentifierDataPthreads_h
+#define ThreadIdentifierDataPthreads_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/Threading.h>
+
+namespace WTF {
+
+// Holds ThreadIdentifier in the thread-specific storage and employs pthreads-specific 2-pass destruction to reliably remove
+// ThreadIdentifier from threadMap. It assumes regular ThreadSpecific types don't use multiple-pass destruction.
+class ThreadIdentifierData : public Noncopyable {
+public:
+    ~ThreadIdentifierData();
+
+    // Creates and puts an instance of ThreadIdentifierData into thread-specific storage.
+    static void initialize(ThreadIdentifier identifier);
+
+    // Returns 0 if thread-specific storage was not initialized.
+    static ThreadIdentifier identifier();
+
+private:
+    ThreadIdentifierData(ThreadIdentifier identifier)
+        : m_identifier(identifier)
+        , m_isDestroyedOnce(false)
+    {
+    }
+
+    // This thread-specific destructor is called 2 times when thread terminates:
+    // - first, when all the other thread-specific destructors are called, it simply remembers it was 'destroyed once'
+    // and re-sets itself into the thread-specific slot to make Pthreads to call it again later.
+    // - second, after all thread-specific destructors were invoked, it gets called again - this time, we remove the
+    // ThreadIdentifier from the threadMap, completing the cleanup.
+    static void destruct(void* data);
+
+    static void initializeKeyOnceHelper();
+    static void initializeKeyOnce();
+
+    ThreadIdentifier m_identifier;
+    bool m_isDestroyedOnce;
+    static pthread_key_t m_key;
+};
+
+} // namespace WTF
+
+#endif // ThreadIdentifierDataPthreads_h
+
+
index b07a9a21e40851c037f2b8199ee94283079dc63c..3abbc5847d72f1f69a4c1e0230a3031e31fc3992 100644 (file)
 #include <pthread.h>
 #elif PLATFORM(QT)
 #include <QThreadStorage>
 #include <pthread.h>
 #elif PLATFORM(QT)
 #include <QThreadStorage>
-#elif PLATFORM(WIN_OS)
+#elif OS(WINDOWS)
 #include <windows.h>
 #endif
 
 namespace WTF {
 
 #include <windows.h>
 #endif
 
 namespace WTF {
 
-#if !USE(PTHREADS) && !PLATFORM(QT) && PLATFORM(WIN_OS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS)
 // ThreadSpecificThreadExit should be called each time when a thread is detached.
 // This is done automatically for threads created with WTF::createThread.
 void ThreadSpecificThreadExit();
 #endif
 
 // ThreadSpecificThreadExit should be called each time when a thread is detached.
 // This is done automatically for threads created with WTF::createThread.
 void ThreadSpecificThreadExit();
 #endif
 
-template<typename T> class ThreadSpecific : Noncopyable {
+template<typename T> class ThreadSpecific : public Noncopyable {
 public:
     ThreadSpecific();
     T* operator->();
 public:
     ThreadSpecific();
     T* operator->();
@@ -68,7 +68,7 @@ public:
     ~ThreadSpecific();
 
 private:
     ~ThreadSpecific();
 
 private:
-#if !USE(PTHREADS) && !PLATFORM(QT) && PLATFORM(WIN_OS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS)
     friend void ThreadSpecificThreadExit();
 #endif
     
     friend void ThreadSpecificThreadExit();
 #endif
     
@@ -76,27 +76,59 @@ private:
     void set(T*);
     void static destroy(void* ptr);
 
     void set(T*);
     void static destroy(void* ptr);
 
-#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(WIN_OS)
+#if USE(PTHREADS) || PLATFORM(QT) || OS(WINDOWS)
     struct Data : Noncopyable {
         Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
     struct Data : Noncopyable {
         Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
+#if PLATFORM(QT)
+        ~Data() { owner->destroy(this); }
+#endif
 
         T* value;
         ThreadSpecific<T>* owner;
 
         T* value;
         ThreadSpecific<T>* owner;
-#if !USE(PTHREADS)
+#if !USE(PTHREADS) && !PLATFORM(QT)
         void (*destructor)(void*);
 #endif
     };
 #endif
 
         void (*destructor)(void*);
 #endif
     };
 #endif
 
+#if ENABLE(SINGLE_THREADED)
+    T* m_value;
+#else
 #if USE(PTHREADS)
     pthread_key_t m_key;
 #elif PLATFORM(QT)
     QThreadStorage<Data*> m_key;
 #if USE(PTHREADS)
     pthread_key_t m_key;
 #elif PLATFORM(QT)
     QThreadStorage<Data*> m_key;
-#elif PLATFORM(WIN_OS)
+#elif OS(WINDOWS)
     int m_index;
 #endif
     int m_index;
 #endif
+#endif
 };
 
 };
 
+#if ENABLE(SINGLE_THREADED)
+template<typename T>
+inline ThreadSpecific<T>::ThreadSpecific()
+    : m_value(0)
+{
+}
+
+template<typename T>
+inline ThreadSpecific<T>::~ThreadSpecific()
+{
+}
+
+template<typename T>
+inline T* ThreadSpecific<T>::get()
+{
+    return m_value;
+}
+
+template<typename T>
+inline void ThreadSpecific<T>::set(T* ptr)
+{
+    ASSERT(!get());
+    m_value = ptr;
+}
+#else
 #if USE(PTHREADS)
 template<typename T>
 inline ThreadSpecific<T>::ThreadSpecific()
 #if USE(PTHREADS)
 template<typename T>
 inline ThreadSpecific<T>::ThreadSpecific()
@@ -136,9 +168,7 @@ inline ThreadSpecific<T>::ThreadSpecific()
 template<typename T>
 inline ThreadSpecific<T>::~ThreadSpecific()
 {
 template<typename T>
 inline ThreadSpecific<T>::~ThreadSpecific()
 {
-    Data* data = static_cast<Data*>(m_key.localData());
-    if (data)
-        data->destructor(data);
+    // Does not invoke destructor functions. QThreadStorage will do it
 }
 
 template<typename T>
 }
 
 template<typename T>
@@ -153,11 +183,10 @@ inline void ThreadSpecific<T>::set(T* ptr)
 {
     ASSERT(!get());
     Data* data = new Data(ptr, this);
 {
     ASSERT(!get());
     Data* data = new Data(ptr, this);
-    data->destructor = &ThreadSpecific<T>::destroy;
     m_key.setLocalData(data);
 }
 
     m_key.setLocalData(data);
 }
 
-#elif PLATFORM(WIN_OS)
+#elif OS(WINDOWS)
 
 // The maximum number of TLS keys that can be created. For simplification, we assume that:
 // 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies.
 
 // The maximum number of TLS keys that can be created. For simplification, we assume that:
 // 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies.
@@ -207,10 +236,12 @@ inline void ThreadSpecific<T>::set(T* ptr)
 #else
 #error ThreadSpecific is not implemented for this platform.
 #endif
 #else
 #error ThreadSpecific is not implemented for this platform.
 #endif
+#endif
 
 template<typename T>
 inline void ThreadSpecific<T>::destroy(void* ptr)
 {
 
 template<typename T>
 inline void ThreadSpecific<T>::destroy(void* ptr)
 {
+#if !ENABLE(SINGLE_THREADED)
     Data* data = static_cast<Data*>(ptr);
 
 #if USE(PTHREADS)
     Data* data = static_cast<Data*>(ptr);
 
 #if USE(PTHREADS)
@@ -218,21 +249,28 @@ inline void ThreadSpecific<T>::destroy(void* ptr)
     // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it.
     pthread_setspecific(data->owner->m_key, ptr);
 #endif
     // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it.
     pthread_setspecific(data->owner->m_key, ptr);
 #endif
-    
+#if PLATFORM(QT)
+    // See comment as above
+    data->owner->m_key.setLocalData(data);
+#endif
+
     data->value->~T();
     fastFree(data->value);
 
 #if USE(PTHREADS)
     pthread_setspecific(data->owner->m_key, 0);
 #elif PLATFORM(QT)
     data->value->~T();
     fastFree(data->value);
 
 #if USE(PTHREADS)
     pthread_setspecific(data->owner->m_key, 0);
 #elif PLATFORM(QT)
-    data->owner->m_key.setLocalData(0);
-#elif PLATFORM(WIN_OS)
+    // Do nothing here
+#elif OS(WINDOWS)
     TlsSetValue(tlsKeys()[data->owner->m_index], 0);
 #else
 #error ThreadSpecific is not implemented for this platform.
 #endif
 
     TlsSetValue(tlsKeys()[data->owner->m_index], 0);
 #else
 #error ThreadSpecific is not implemented for this platform.
 #endif
 
+#if !PLATFORM(QT)
     delete data;
     delete data;
+#endif
+#endif
 }
 
 template<typename T>
 }
 
 template<typename T>
index bd25ee749869d2b1aac78aa25aff882df80d23c6..49de59ec00ae509abaa56b757fdf953532f7697b 100644 (file)
@@ -30,7 +30,7 @@
 
 namespace WTF {
 
 
 namespace WTF {
 
-struct NewThreadContext {
+struct NewThreadContext : FastAllocBase {
     NewThreadContext(ThreadFunction entryPoint, void* data, const char* name)
         : entryPoint(entryPoint)
         , data(data)
     NewThreadContext(ThreadFunction entryPoint, void* data, const char* name)
         : entryPoint(entryPoint)
         , data(data)
@@ -49,13 +49,14 @@ static void* threadEntryPoint(void* contextData)
 {
     NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData);
 
 {
     NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData);
 
-    setThreadNameInternal(context->name);
-
-    // Block until our creating thread has completed any extra setup work
+    // Block until our creating thread has completed any extra setup work, including
+    // establishing ThreadIdentifier.
     {
         MutexLocker locker(context->creationMutex);
     }
 
     {
         MutexLocker locker(context->creationMutex);
     }
 
+    initializeCurrentThreadInternal(context->name);
+
     // Grab the info that we need out of the context, then deallocate it.
     ThreadFunction entryPoint = context->entryPoint;
     void* data = context->data;
     // Grab the info that we need out of the context, then deallocate it.
     ThreadFunction entryPoint = context->entryPoint;
     void* data = context->data;
@@ -75,7 +76,7 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*
 
     NewThreadContext* context = new NewThreadContext(entryPoint, data, name);
 
 
     NewThreadContext* context = new NewThreadContext(entryPoint, data, name);
 
-    // Prevent the thread body from executing until we've established the thread identifier
+    // Prevent the thread body from executing until we've established the thread identifier.
     MutexLocker locker(context->creationMutex);
 
     return createThreadInternal(threadEntryPoint, context, name);
     MutexLocker locker(context->creationMutex);
 
     return createThreadInternal(threadEntryPoint, context, name);
index b12f41fa771c92f98f6ef141698098f894d8272a..1599562ef5191e64b489cb20cab85652e79b100e 100644 (file)
@@ -59,7 +59,9 @@
 #ifndef Threading_h
 #define Threading_h
 
 #ifndef Threading_h
 #define Threading_h
 
-#if PLATFORM(WINCE)
+#include "Platform.h"
+
+#if OS(WINCE)
 #include <windows.h>
 #endif
 
 #include <windows.h>
 #endif
 
 #include <wtf/Locker.h>
 #include <wtf/Noncopyable.h>
 
 #include <wtf/Locker.h>
 #include <wtf/Noncopyable.h>
 
-#if PLATFORM(WIN_OS) && !PLATFORM(WINCE)
+#if OS(WINDOWS) && !OS(WINCE)
 #include <windows.h>
 #include <windows.h>
-#elif PLATFORM(DARWIN)
+#elif OS(DARWIN)
 #include <libkern/OSAtomic.h>
 #include <libkern/OSAtomic.h>
+#elif OS(ANDROID)
+#include <cutils/atomic.h>
 #elif COMPILER(GCC)
 #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))
 #include <ext/atomicity.h>
 #elif COMPILER(GCC)
 #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))
 #include <ext/atomicity.h>
@@ -82,7 +86,7 @@
 #if USE(PTHREADS)
 #include <pthread.h>
 #elif PLATFORM(GTK)
 #if USE(PTHREADS)
 #include <pthread.h>
 #elif PLATFORM(GTK)
-#include <wtf/GOwnPtr.h>
+#include <wtf/gtk/GOwnPtr.h>
 typedef struct _GMutex GMutex;
 typedef struct _GCond GCond;
 #endif
 typedef struct _GMutex GMutex;
 typedef struct _GCond GCond;
 #endif
@@ -117,7 +121,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadN
 
 // Called in the thread during initialization.
 // Helpful for platforms where the thread name must be set from within the thread.
 
 // Called in the thread during initialization.
 // Helpful for platforms where the thread name must be set from within the thread.
-void setThreadNameInternal(const char* threadName);
+void initializeCurrentThreadInternal(const char* threadName);
 
 ThreadIdentifier currentThread();
 bool isMainThread();
 
 ThreadIdentifier currentThread();
 bool isMainThread();
@@ -126,7 +130,11 @@ void detachThread(ThreadIdentifier);
 
 #if USE(PTHREADS)
 typedef pthread_mutex_t PlatformMutex;
 
 #if USE(PTHREADS)
 typedef pthread_mutex_t PlatformMutex;
+#if HAVE(PTHREAD_RWLOCK)
 typedef pthread_rwlock_t PlatformReadWriteLock;
 typedef pthread_rwlock_t PlatformReadWriteLock;
+#else
+typedef void* PlatformReadWriteLock;
+#endif
 typedef pthread_cond_t PlatformCondition;
 #elif PLATFORM(GTK)
 typedef GOwnPtr<GMutex> PlatformMutex;
 typedef pthread_cond_t PlatformCondition;
 #elif PLATFORM(GTK)
 typedef GOwnPtr<GMutex> PlatformMutex;
@@ -136,7 +144,7 @@ typedef GOwnPtr<GCond> PlatformCondition;
 typedef QT_PREPEND_NAMESPACE(QMutex)* PlatformMutex;
 typedef void* PlatformReadWriteLock; // FIXME: Implement.
 typedef QT_PREPEND_NAMESPACE(QWaitCondition)* PlatformCondition;
 typedef QT_PREPEND_NAMESPACE(QMutex)* PlatformMutex;
 typedef void* PlatformReadWriteLock; // FIXME: Implement.
 typedef QT_PREPEND_NAMESPACE(QWaitCondition)* PlatformCondition;
-#elif PLATFORM(WIN_OS)
+#elif OS(WINDOWS)
 struct PlatformMutex {
     CRITICAL_SECTION m_internalMutex;
     size_t m_recursionCount;
 struct PlatformMutex {
     CRITICAL_SECTION m_internalMutex;
     size_t m_recursionCount;
@@ -159,7 +167,7 @@ typedef void* PlatformReadWriteLock;
 typedef void* PlatformCondition;
 #endif
     
 typedef void* PlatformCondition;
 #endif
     
-class Mutex : Noncopyable {
+class Mutex : public Noncopyable {
 public:
     Mutex();
     ~Mutex();
 public:
     Mutex();
     ~Mutex();
@@ -176,7 +184,7 @@ private:
 
 typedef Locker<Mutex> MutexLocker;
 
 
 typedef Locker<Mutex> MutexLocker;
 
-class ReadWriteLock : Noncopyable {
+class ReadWriteLock : public Noncopyable {
 public:
     ReadWriteLock();
     ~ReadWriteLock();
 public:
     ReadWriteLock();
     ~ReadWriteLock();
@@ -193,7 +201,7 @@ private:
     PlatformReadWriteLock m_readWriteLock;
 };
 
     PlatformReadWriteLock m_readWriteLock;
 };
 
-class ThreadCondition : Noncopyable {
+class ThreadCondition : public Noncopyable {
 public:
     ThreadCondition();
     ~ThreadCondition();
 public:
     ThreadCondition();
     ~ThreadCondition();
@@ -209,32 +217,37 @@ private:
     PlatformCondition m_condition;
 };
 
     PlatformCondition m_condition;
 };
 
-#if PLATFORM(WIN_OS)
+#if OS(WINDOWS)
 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1
 
 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1
 
-#if COMPILER(MINGW) || COMPILER(MSVC7) || PLATFORM(WINCE)
-inline void atomicIncrement(int* addend) { InterlockedIncrement(reinterpret_cast<long*>(addend)); }
+#if COMPILER(MINGW) || COMPILER(MSVC7) || OS(WINCE)
+inline int atomicIncrement(int* addend) { return InterlockedIncrement(reinterpret_cast<long*>(addend)); }
 inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); }
 #else
 inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); }
 #else
-inline void atomicIncrement(int volatile* addend) { InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); }
+inline int atomicIncrement(int volatile* addend) { return InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); }
 inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); }
 #endif
 
 inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); }
 #endif
 
-#elif PLATFORM(DARWIN)
+#elif OS(DARWIN)
 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1
 
 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1
 
-inline void atomicIncrement(int volatile* addend) { OSAtomicIncrement32Barrier(const_cast<int*>(addend)); }
+inline int atomicIncrement(int volatile* addend) { return OSAtomicIncrement32Barrier(const_cast<int*>(addend)); }
 inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); }
 
 inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); }
 
-#elif COMPILER(GCC)
+#elif OS(ANDROID)
+
+inline int atomicIncrement(int volatile* addend) { return android_atomic_inc(addend); }
+inline int atomicDecrement(int volatile* addend) { return android_atomic_dec(addend); }
+
+#elif COMPILER(GCC) && !CPU(SPARC64) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc
 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1
 
 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1
 
-inline void atomicIncrement(int volatile* addend) { __gnu_cxx::__atomic_add(addend, 1); }
+inline int atomicIncrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, 1) + 1; }
 inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; }
 
 #endif
 
 inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; }
 
 #endif
 
-class ThreadSafeSharedBase : Noncopyable {
+class ThreadSafeSharedBase : public Noncopyable {
 public:
     ThreadSafeSharedBase(int initialRefCount = 1)
         : m_refCount(initialRefCount)
 public:
     ThreadSafeSharedBase(int initialRefCount = 1)
         : m_refCount(initialRefCount)
@@ -323,6 +336,11 @@ using WTF::ThreadCondition;
 using WTF::ThreadIdentifier;
 using WTF::ThreadSafeShared;
 
 using WTF::ThreadIdentifier;
 using WTF::ThreadSafeShared;
 
+#if USE(LOCKFREE_THREADSAFESHARED)
+using WTF::atomicDecrement;
+using WTF::atomicIncrement;
+#endif
+
 using WTF::createThread;
 using WTF::currentThread;
 using WTF::isMainThread;
 using WTF::createThread;
 using WTF::currentThread;
 using WTF::isMainThread;
index 46f23d211f1518b273c76de385870968205b2ed7..2e8a259f4dca61d908f09b6544a267e6f22558ca 100644 (file)
 #include "config.h"
 #include "Threading.h"
 
 #include "config.h"
 #include "Threading.h"
 
+#if ENABLE(SINGLE_THREADED)
+
 namespace WTF {
 
 void initializeThreading() { }
 ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return ThreadIdentifier(); }
 namespace WTF {
 
 void initializeThreading() { }
 ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return ThreadIdentifier(); }
-void setThreadNameInternal(const char*) { }
+void initializeCurrentThreadInternal(const char*) { }
 int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; }
 void detachThread(ThreadIdentifier) { }
 ThreadIdentifier currentThread() { return ThreadIdentifier(); }
 int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; }
 void detachThread(ThreadIdentifier) { }
 ThreadIdentifier currentThread() { return ThreadIdentifier(); }
@@ -57,3 +59,5 @@ void lockAtomicallyInitializedStaticMutex() { }
 void unlockAtomicallyInitializedStaticMutex() { }
 
 } // namespace WebCore
 void unlockAtomicallyInitializedStaticMutex() { }
 
 } // namespace WebCore
+
+#endif
index 0c6db2d1ec60c794b4f6a5264a55c9b612d30187..2feb80829544f4d7ce59cbe8a5ff86e4dfba109d 100644 (file)
 #include "MainThread.h"
 #include "RandomNumberSeed.h"
 #include "StdLibExtras.h"
 #include "MainThread.h"
 #include "RandomNumberSeed.h"
 #include "StdLibExtras.h"
+#include "ThreadIdentifierDataPthreads.h"
+#include "ThreadSpecific.h"
 #include "UnusedParam.h"
 #include <errno.h>
 #include "UnusedParam.h"
 #include <errno.h>
+
+#if !COMPILER(MSVC)
 #include <limits.h>
 #include <sys/time.h>
 #include <limits.h>
 #include <sys/time.h>
+#endif
 
 
-#if PLATFORM(ANDROID)
+#if OS(ANDROID)
 #include "jni_utility.h"
 #endif
 
 #include "jni_utility.h"
 #endif
 
@@ -52,7 +57,11 @@ typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
 
 static Mutex* atomicallyInitializedStaticMutex;
 
 
 static Mutex* atomicallyInitializedStaticMutex;
 
-static ThreadIdentifier mainThreadIdentifier; // The thread that was the first to call initializeThreading(), which must be the main thread.
+#if !OS(DARWIN) || PLATFORM(CHROMIUM) || USE(WEB_THREAD)
+static pthread_t mainThread; // The thread that was the first to call initializeThreading(), which must be the main thread.
+#endif
+
+void clearPthreadHandleForIdentifier(ThreadIdentifier);
 
 static Mutex& threadMapMutex()
 {
 
 static Mutex& threadMapMutex()
 {
@@ -66,7 +75,9 @@ void initializeThreading()
         atomicallyInitializedStaticMutex = new Mutex;
         threadMapMutex();
         initializeRandomNumberGenerator();
         atomicallyInitializedStaticMutex = new Mutex;
         threadMapMutex();
         initializeRandomNumberGenerator();
-        mainThreadIdentifier = currentThread();
+#if !OS(DARWIN) || PLATFORM(CHROMIUM) || USE(WEB_THREAD)
+        mainThread = pthread_self();
+#endif
         initializeMainThread();
     }
 }
         initializeMainThread();
     }
 }
@@ -101,7 +112,7 @@ static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle
     return 0;
 }
 
     return 0;
 }
 
-static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle)
+static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle)
 {
     ASSERT(!identifierByPthreadHandle(pthreadHandle));
 
 {
     ASSERT(!identifierByPthreadHandle(pthreadHandle));
 
@@ -121,7 +132,7 @@ static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
     return threadMap().get(id);
 }
 
     return threadMap().get(id);
 }
 
-static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
+void clearPthreadHandleForIdentifier(ThreadIdentifier id)
 {
     MutexLocker locker(threadMapMutex());
 
 {
     MutexLocker locker(threadMapMutex());
 
@@ -130,7 +141,7 @@ static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
     threadMap().remove(id);
 }
 
     threadMap().remove(id);
 }
 
-#if PLATFORM(ANDROID)
+#if OS(ANDROID)
 // On the Android platform, threads must be registered with the VM before they run.
 struct ThreadData {
     ThreadFunction entryPoint;
 // On the Android platform, threads must be registered with the VM before they run.
 struct ThreadData {
     ThreadFunction entryPoint;
@@ -160,6 +171,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
 
     if (pthread_create(&threadHandle, 0, runThreadWithRegistration, static_cast<void*>(threadData))) {
         LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
 
     if (pthread_create(&threadHandle, 0, runThreadWithRegistration, static_cast<void*>(threadData))) {
         LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
+        delete threadData;
         return 0;
     }
     return establishIdentifierForPthreadHandle(threadHandle);
         return 0;
     }
     return establishIdentifierForPthreadHandle(threadHandle);
@@ -177,13 +189,17 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
 }
 #endif
 
 }
 #endif
 
-void setThreadNameInternal(const char* threadName)
+void initializeCurrentThreadInternal(const char* threadName)
 {
 #if HAVE(PTHREAD_SETNAME_NP)
     pthread_setname_np(threadName);
 #else
     UNUSED_PARAM(threadName);
 #endif
 {
 #if HAVE(PTHREAD_SETNAME_NP)
     pthread_setname_np(threadName);
 #else
     UNUSED_PARAM(threadName);
 #endif
+
+    ThreadIdentifier id = identifierByPthreadHandle(pthread_self());
+    ASSERT(id);
+    ThreadIdentifierData::initialize(id);
 }
 
 int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
 }
 
 int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
@@ -191,12 +207,13 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
     ASSERT(threadID);
 
     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
     ASSERT(threadID);
 
     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
+    if (!pthreadHandle)
+        return 0;
 
     int joinResult = pthread_join(pthreadHandle, result);
     if (joinResult == EDEADLK)
         LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
 
 
     int joinResult = pthread_join(pthreadHandle, result);
     if (joinResult == EDEADLK)
         LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
 
-    clearPthreadHandleForIdentifier(threadID);
     return joinResult;
 }
 
     return joinResult;
 }
 
@@ -205,23 +222,31 @@ void detachThread(ThreadIdentifier threadID)
     ASSERT(threadID);
 
     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
     ASSERT(threadID);
 
     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
+    if (!pthreadHandle)
+        return;
 
     pthread_detach(pthreadHandle);
 
     pthread_detach(pthreadHandle);
-
-    clearPthreadHandleForIdentifier(threadID);
 }
 
 ThreadIdentifier currentThread()
 {
 }
 
 ThreadIdentifier currentThread()
 {
-    pthread_t currentThread = pthread_self();
-    if (ThreadIdentifier id = identifierByPthreadHandle(currentThread))
+    ThreadIdentifier id = ThreadIdentifierData::identifier();
+    if (id)
         return id;
         return id;
-    return establishIdentifierForPthreadHandle(currentThread);
+
+    // Not a WTF-created thread, ThreadIdentifier is not established yet.
+    id = establishIdentifierForPthreadHandle(pthread_self());
+    ThreadIdentifierData::initialize(id);
+    return id;
 }
 
 bool isMainThread()
 {
 }
 
 bool isMainThread()
 {
-    return currentThread() == mainThreadIdentifier;
+#if OS(DARWIN) && !PLATFORM(CHROMIUM) && !USE(WEB_THREAD)
+    return pthread_main_np();
+#else
+    return pthread_equal(pthread_self(), mainThread);
+#endif
 }
 
 Mutex::Mutex()
 }
 
 Mutex::Mutex()
@@ -259,7 +284,7 @@ void Mutex::unlock()
     ASSERT_UNUSED(result, !result);
 }
 
     ASSERT_UNUSED(result, !result);
 }
 
-
+#if HAVE(PTHREAD_RWLOCK)
 ReadWriteLock::ReadWriteLock()
 {
     pthread_rwlock_init(&m_readWriteLock, NULL);
 ReadWriteLock::ReadWriteLock()
 {
     pthread_rwlock_init(&m_readWriteLock, NULL);
@@ -313,6 +338,7 @@ void ReadWriteLock::unlock()
     int result = pthread_rwlock_unlock(&m_readWriteLock);
     ASSERT_UNUSED(result, !result);
 }
     int result = pthread_rwlock_unlock(&m_readWriteLock);
     ASSERT_UNUSED(result, !result);
 }
+#endif  // HAVE(PTHREAD_RWLOCK)
 
 ThreadCondition::ThreadCondition()
 { 
 
 ThreadCondition::ThreadCondition()
 { 
index ea186564b0009f5259805eadb3f6fff88ea96d0b..73c3f0c14d1cef386caf344f261eb5f8354abb00 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Google Inc. All rights reserved.
 /*
  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "Threading.h"
 
 #include "MainThread.h"
 #include "Threading.h"
 
 #include "MainThread.h"
-#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+#if !USE(PTHREADS) && OS(WINDOWS)
 #include "ThreadSpecific.h"
 #endif
 #include "ThreadSpecific.h"
 #endif
+#if !OS(WINCE)
 #include <process.h>
 #include <process.h>
+#endif
+#if HAVE(ERRNO_H)
+#include <errno.h>
+#else
+#define NO_ERRNO
+#endif
 #include <windows.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/HashMap.h>
 #include <windows.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/HashMap.h>
@@ -110,7 +118,7 @@ typedef struct tagTHREADNAME_INFO {
 } THREADNAME_INFO;
 #pragma pack(pop)
 
 } THREADNAME_INFO;
 #pragma pack(pop)
 
-void setThreadNameInternal(const char* szThreadName)
+void initializeCurrentThreadInternal(const char* szThreadName)
 {
     THREADNAME_INFO info;
     info.dwType = 0x1000;
 {
     THREADNAME_INFO info;
     info.dwType = 0x1000;
@@ -153,7 +161,7 @@ void initializeThreading()
         initializeRandomNumberGenerator();
         initializeMainThread();
         mainThreadIdentifier = currentThread();
         initializeRandomNumberGenerator();
         initializeMainThread();
         mainThreadIdentifier = currentThread();
-        setThreadNameInternal("Main Thread");
+        initializeCurrentThreadInternal("Main Thread");
     }
 }
 
     }
 }
 
@@ -197,7 +205,7 @@ static unsigned __stdcall wtfThreadEntryPoint(void* param)
 
     void* result = invocation.function(invocation.data);
 
 
     void* result = invocation.function(invocation.data);
 
-#if !USE(PTHREADS) && PLATFORM(WIN_OS)
+#if !USE(PTHREADS) && OS(WINDOWS)
     // Do the TLS cleanup.
     ThreadSpecificThreadExit();
 #endif
     // Do the TLS cleanup.
     ThreadSpecificThreadExit();
 #endif
@@ -210,9 +218,21 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
     unsigned threadIdentifier = 0;
     ThreadIdentifier threadID = 0;
     ThreadFunctionInvocation* invocation = new ThreadFunctionInvocation(entryPoint, data);
     unsigned threadIdentifier = 0;
     ThreadIdentifier threadID = 0;
     ThreadFunctionInvocation* invocation = new ThreadFunctionInvocation(entryPoint, data);
+#if OS(WINCE)
+    // This is safe on WINCE, since CRT is in the core and innately multithreaded.
+    // On desktop Windows, need to use _beginthreadex (not available on WinCE) if using any CRT functions
+    HANDLE threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)wtfThreadEntryPoint, invocation, 0, (LPDWORD)&threadIdentifier);
+#else
     HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation, 0, &threadIdentifier));
     HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation, 0, &threadIdentifier));
+#endif
     if (!threadHandle) {
     if (!threadHandle) {
+#if OS(WINCE)
+        LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, ::GetLastError());
+#elif defined(NO_ERRNO)
+        LOG_ERROR("Failed to create thread at entry point %p with data %p.", entryPoint, data);
+#else
         LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, errno);
         LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, errno);
+#endif
         return 0;
     }
 
         return 0;
     }
 
index 36fc6c68f901b063216907105b9e1f19e601ec39..9e51ad0813419d1559848764f7c4de75da19e26b 100644 (file)
@@ -1,6 +1,6 @@
  /*
  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
  /*
  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -101,6 +101,20 @@ COMPILE_ASSERT((!IsSameType<int, int*>::value), WTF_IsSameType_int_int_pointer_f
 COMPILE_ASSERT((!IsSameType<bool, const bool>::value), WTF_IsSameType_const_change_false);
 COMPILE_ASSERT((!IsSameType<bool, volatile bool>::value), WTF_IsSameType_volatile_change_false);
 
 COMPILE_ASSERT((!IsSameType<bool, const bool>::value), WTF_IsSameType_const_change_false);
 COMPILE_ASSERT((!IsSameType<bool, volatile bool>::value), WTF_IsSameType_volatile_change_false);
 
+template <typename T>
+class TestBaseClass {
+};
+
+class TestDerivedClass : public TestBaseClass<int> {
+};
+
+COMPILE_ASSERT((IsSubclass<TestDerivedClass, TestBaseClass<int> >::value), WTF_Test_IsSubclass_Derived_From_Base);
+COMPILE_ASSERT((!IsSubclass<TestBaseClass<int>, TestDerivedClass>::value), WTF_Test_IsSubclass_Base_From_Derived);
+COMPILE_ASSERT((IsSubclassOfTemplate<TestDerivedClass, TestBaseClass>::value), WTF_Test_IsSubclassOfTemplate_Base_From_Derived);
+COMPILE_ASSERT((IsSameType<RemoveTemplate<TestBaseClass<int>, TestBaseClass>::Type, int>::value), WTF_Test_RemoveTemplate);
+COMPILE_ASSERT((IsSameType<RemoveTemplate<int, TestBaseClass>::Type, int>::value), WTF_Test_RemoveTemplate_WithoutTemplate);
+
+
 COMPILE_ASSERT((IsSameType<bool, RemoveConst<const bool>::Type>::value), WTF_test_RemoveConst_const_bool);
 COMPILE_ASSERT((!IsSameType<bool, RemoveConst<volatile bool>::Type>::value), WTF_test_RemoveConst_volatile_bool);
 
 COMPILE_ASSERT((IsSameType<bool, RemoveConst<const bool>::Type>::value), WTF_test_RemoveConst_const_bool);
 COMPILE_ASSERT((!IsSameType<bool, RemoveConst<volatile bool>::Type>::value), WTF_test_RemoveConst_volatile_bool);
 
index 6ce6a3e5cc16daac8d970761c9981f70f6b3b6dc..62dbc4926c1c131731cec9db333e2e25803a1384 100644 (file)
@@ -1,6 +1,6 @@
  /*
  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
  /*
  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -104,6 +104,40 @@ namespace WTF {
         static const bool value = true;
     };
 
         static const bool value = true;
     };
 
+    template <typename T, typename U> class IsSubclass {
+        typedef char YesType;
+        struct NoType {
+            char padding[8];
+        };
+
+        static YesType subclassCheck(U*);
+        static NoType subclassCheck(...);
+        static T* t;
+    public:
+        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
+    };
+
+    template <typename T, template<class V> class U> class IsSubclassOfTemplate {
+        typedef char YesType;
+        struct NoType {
+            char padding[8];
+        };
+
+        template<typename W> static YesType subclassCheck(U<W>*);
+        static NoType subclassCheck(...);
+        static T* t;
+    public:
+        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
+    };
+
+    template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate {
+        typedef T Type;
+    };
+
+    template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate<OuterTemplate<T>, OuterTemplate> {
+        typedef T Type;
+    };
+
     template <typename T> struct RemoveConst {
         typedef T Type;
     };
     template <typename T> struct RemoveConst {
         typedef T Type;
     };
@@ -155,7 +189,7 @@ namespace WTF {
     typedef IntegralConstant<bool, true>  true_type;
     typedef IntegralConstant<bool, false> false_type;
 
     typedef IntegralConstant<bool, true>  true_type;
     typedef IntegralConstant<bool, false> false_type;
 
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER)
     // VC8 (VS2005) and later have built-in compiler support for HasTrivialConstructor / HasTrivialDestructor,
     // but for some unexplained reason it doesn't work on built-in types.
     template <typename T> struct HasTrivialConstructor : public IntegralConstant<bool, __has_trivial_constructor(T)>{ };
     // VC8 (VS2005) and later have built-in compiler support for HasTrivialConstructor / HasTrivialDestructor,
     // but for some unexplained reason it doesn't work on built-in types.
     template <typename T> struct HasTrivialConstructor : public IntegralConstant<bool, __has_trivial_constructor(T)>{ };
index 519f5189492bc64a5b976807ca915d33b66aa6a4..34e24942fc60efe3a93527a928c9a8a0cb49eb53 100644 (file)
 
 // On Mac OS X, the VM subsystem allows tagging memory requested from mmap and vm_map
 // in order to aid tools that inspect system memory use. 
 
 // On Mac OS X, the VM subsystem allows tagging memory requested from mmap and vm_map
 // in order to aid tools that inspect system memory use. 
-#if PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER)
+#if OS(DARWIN) && !defined(BUILDING_ON_TIGER)
 
 #include <mach/vm_statistics.h>
 
 
 #include <mach/vm_statistics.h>
 
+#if defined(VM_MEMORY_TCMALLOC)
+#define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(VM_MEMORY_TCMALLOC)
+#else
+#define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(53)
+#endif // defined(VM_MEMORY_TCMALLOC)
+
 #if defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
 #define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE)
 #define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE)
 #if defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
 #define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE)
 #define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE)
 #define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(65)
 #endif // defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
 
 #define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(65)
 #endif // defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
 
-#else // PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER)
+#if defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
+#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
+#else
+#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(69)
+#endif // defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
+
+#else // OS(DARWIN) && !defined(BUILDING_ON_TIGER)
 
 
+#define VM_TAG_FOR_TCMALLOC_MEMORY -1
 #define VM_TAG_FOR_COLLECTOR_MEMORY -1
 #define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1
 #define VM_TAG_FOR_REGISTERFILE_MEMORY -1
 #define VM_TAG_FOR_COLLECTOR_MEMORY -1
 #define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1
 #define VM_TAG_FOR_REGISTERFILE_MEMORY -1
+#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY -1
 
 
-#endif // PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER)
+#endif // OS(DARWIN) && !defined(BUILDING_ON_TIGER)
 
 #endif // VMTags_h
 
 #endif // VMTags_h
diff --git a/wtf/ValueCheck.h b/wtf/ValueCheck.h
new file mode 100644 (file)
index 0000000..cd321b8
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ValueCheck_h
+#define ValueCheck_h
+
+// For malloc_size and _msize.
+#if OS(DARWIN)
+#include <malloc/malloc.h>
+#elif COMPILER(MSVC)
+#include <malloc.h>
+#endif
+
+namespace WTF {
+
+template<typename T> struct ValueCheck {
+    typedef T TraitType;
+    static void checkConsistency(const T&) { }
+};
+
+#if !ASSERT_DISABLED
+template<typename P> struct ValueCheck<P*> {
+    typedef P* TraitType;
+    static void checkConsistency(const P* p)
+    {
+        if (!p)
+            return;
+#if (defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) || !defined(NDEBUG)
+#if OS(DARWIN)
+        ASSERT(malloc_size(p));
+#elif COMPILER(MSVC)
+        ASSERT(_msize(const_cast<P*>(p)));
+#endif
+#endif
+        ValueCheck<P>::checkConsistency(*p);
+    }
+};
+#endif
+
+}
+
+#endif // ValueCheck_h
index f8a5be2798bb4405172eeda933ca282cf45178d4..5054449e4fbd7f276f415b03359b7211371d2466 100644 (file)
@@ -24,6 +24,7 @@
 #include "FastAllocBase.h"
 #include "Noncopyable.h"
 #include "NotFound.h"
 #include "FastAllocBase.h"
 #include "Noncopyable.h"
 #include "NotFound.h"
+#include "ValueCheck.h"
 #include "VectorTraits.h"
 #include <limits>
 #include <utility>
 #include "VectorTraits.h"
 #include <limits>
 #include <utility>
@@ -63,8 +64,15 @@ namespace WTF {
     template <size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); };
     template <size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); };
 
     template <size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); };
     template <size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); };
 
+    template <size_t size, size_t alignment>
+    void swap(AlignedBuffer<size, alignment>& a, AlignedBuffer<size, alignment>& b)
+    {
+        for (size_t i = 0; i < size; ++i)
+            std::swap(a.buffer[i], b.buffer[i]);
+    }
+
     template <bool needsDestruction, typename T>
     template <bool needsDestruction, typename T>
-    class VectorDestructor;
+    struct VectorDestructor;
 
     template<typename T>
     struct VectorDestructor<false, T>
 
     template<typename T>
     struct VectorDestructor<false, T>
@@ -83,7 +91,7 @@ namespace WTF {
     };
 
     template <bool needsInitialization, bool canInitializeWithMemset, typename T>
     };
 
     template <bool needsInitialization, bool canInitializeWithMemset, typename T>
-    class VectorInitializer;
+    struct VectorInitializer;
 
     template<bool ignore, typename T>
     struct VectorInitializer<false, ignore, T>
 
     template<bool ignore, typename T>
     struct VectorInitializer<false, ignore, T>
@@ -111,7 +119,7 @@ namespace WTF {
     };
 
     template <bool canMoveWithMemcpy, typename T>
     };
 
     template <bool canMoveWithMemcpy, typename T>
-    class VectorMover;
+    struct VectorMover;
 
     template<typename T>
     struct VectorMover<false, T>
 
     template<typename T>
     struct VectorMover<false, T>
@@ -155,7 +163,7 @@ namespace WTF {
     };
 
     template <bool canCopyWithMemcpy, typename T>
     };
 
     template <bool canCopyWithMemcpy, typename T>
-    class VectorCopier;
+    struct VectorCopier;
 
     template<typename T>
     struct VectorCopier<false, T>
 
     template<typename T>
     struct VectorCopier<false, T>
@@ -180,7 +188,7 @@ namespace WTF {
     };
 
     template <bool canFillWithMemset, typename T>
     };
 
     template <bool canFillWithMemset, typename T>
-    class VectorFiller;
+    struct VectorFiller;
 
     template<typename T>
     struct VectorFiller<false, T>
 
     template<typename T>
     struct VectorFiller<false, T>
@@ -205,7 +213,7 @@ namespace WTF {
     };
     
     template<bool canCompareWithMemcmp, typename T>
     };
     
     template<bool canCompareWithMemcmp, typename T>
-    class VectorComparer;
+    struct VectorComparer;
     
     template<typename T>
     struct VectorComparer<false, T>
     
     template<typename T>
     struct VectorComparer<false, T>
@@ -268,7 +276,7 @@ namespace WTF {
     };
 
     template<typename T>
     };
 
     template<typename T>
-    class VectorBufferBase : Noncopyable {
+    class VectorBufferBase : public Noncopyable {
     public:
         void allocateBuffer(size_t newCapacity)
         {
     public:
         void allocateBuffer(size_t newCapacity)
         {
@@ -404,6 +412,27 @@ namespace WTF {
             Base::deallocateBuffer(bufferToDeallocate);
         }
         
             Base::deallocateBuffer(bufferToDeallocate);
         }
         
+        void swap(VectorBuffer<T, inlineCapacity>& other)
+        {
+            if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) {
+                WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
+                std::swap(m_capacity, other.m_capacity);
+            } else if (buffer() == inlineBuffer()) {
+                m_buffer = other.m_buffer;
+                other.m_buffer = other.inlineBuffer();
+                WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
+                std::swap(m_capacity, other.m_capacity);
+            } else if (other.buffer() == other.inlineBuffer()) {
+                other.m_buffer = m_buffer;
+                m_buffer = inlineBuffer();
+                WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
+                std::swap(m_capacity, other.m_capacity);
+            } else {
+                std::swap(m_buffer, other.m_buffer);
+                std::swap(m_capacity, other.m_capacity);
+            }
+        }
+
         void restoreInlineBufferIfNeeded()
         {
             if (m_buffer)
         void restoreInlineBufferIfNeeded()
         {
             if (m_buffer)
@@ -563,6 +592,8 @@ namespace WTF {
             m_buffer.swap(other.m_buffer);
         }
 
             m_buffer.swap(other.m_buffer);
         }
 
+        void checkConsistency();
+
     private:
         void expandCapacity(size_t newMinCapacity);
         const T* expandCapacity(size_t newMinCapacity, const T*);
     private:
         void expandCapacity(size_t newMinCapacity);
         const T* expandCapacity(size_t newMinCapacity, const T*);
@@ -939,7 +970,7 @@ namespace WTF {
     inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length)
     {
         ASSERT(position < size());
     inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length)
     {
         ASSERT(position < size());
-        ASSERT(position + length < size());
+        ASSERT(position + length <= size());
         T* beginSpot = begin() + position;
         T* endSpot = beginSpot + length;
         TypeOperations::destruct(beginSpot, endSpot); 
         T* beginSpot = begin() + position;
         T* endSpot = beginSpot + length;
         TypeOperations::destruct(beginSpot, endSpot); 
@@ -963,6 +994,15 @@ namespace WTF {
         return buffer;
     }
 
         return buffer;
     }
 
+    template<typename T, size_t inlineCapacity>
+    inline void Vector<T, inlineCapacity>::checkConsistency()
+    {
+#if !ASSERT_DISABLED
+        for (size_t i = 0; i < size(); ++i)
+            ValueCheck<T>::checkConsistency(at(i));
+#endif
+    }
+
     template<typename T, size_t inlineCapacity>
     void deleteAllValues(const Vector<T, inlineCapacity>& collection)
     {
     template<typename T, size_t inlineCapacity>
     void deleteAllValues(const Vector<T, inlineCapacity>& collection)
     {
@@ -993,6 +1033,15 @@ namespace WTF {
         return !(a == b);
     }
 
         return !(a == b);
     }
 
+#if !ASSERT_DISABLED
+    template<typename T> struct ValueCheck<Vector<T> > {
+        typedef Vector<T> TraitType;
+        static void checkConsistency(const Vector<T>& v)
+        {
+            v.checkConsistency();
+        }
+    };
+#endif
 
 } // namespace WTF
 
 
 } // namespace WTF
 
index 7974b9a77e7544d9dacc8ff6b1fd8d211fb49035..bf7787834d2a6c1e3c97abf41dfcec5fc5af59ac 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef WTF_VectorTraits_h
 #define WTF_VectorTraits_h
 
 #ifndef WTF_VectorTraits_h
 #define WTF_VectorTraits_h
 
+#include "OwnPtr.h"
 #include "RefPtr.h"
 #include "TypeTraits.h"
 #include <utility>
 #include "RefPtr.h"
 #include "TypeTraits.h"
 #include <utility>
@@ -31,7 +32,7 @@ using std::pair;
 namespace WTF {
 
     template<bool isPod, typename T>
 namespace WTF {
 
     template<bool isPod, typename T>
-    class VectorTraitsBase;
+    struct VectorTraitsBase;
 
     template<typename T>
     struct VectorTraitsBase<false, T>
 
     template<typename T>
     struct VectorTraitsBase<false, T>
@@ -71,11 +72,14 @@ namespace WTF {
         static const bool canCompareWithMemcmp = true;
     };
 
         static const bool canCompareWithMemcmp = true;
     };
 
-    // we know RefPtr is simple enough that initializing to 0 and moving with memcpy
+    // we know OwnPtr and RefPtr are simple enough that initializing to 0 and moving with memcpy
     // (and then not destructing the original) will totally work
     template<typename P>
     struct VectorTraits<RefPtr<P> > : SimpleClassVectorTraits { };
     // (and then not destructing the original) will totally work
     template<typename P>
     struct VectorTraits<RefPtr<P> > : SimpleClassVectorTraits { };
-    
+
+    template<typename P>
+    struct VectorTraits<OwnPtr<P> > : SimpleClassVectorTraits { };
+
     template<typename P>
     struct VectorTraits<std::auto_ptr<P> > : SimpleClassVectorTraits { };
 
     template<typename P>
     struct VectorTraits<std::auto_ptr<P> > : SimpleClassVectorTraits { };
 
diff --git a/wtf/android/AndroidThreading.h b/wtf/android/AndroidThreading.h
new file mode 100644 (file)
index 0000000..27f548c
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AndroidThreading_h
+#define AndroidThreading_h
+
+namespace WTF {
+
+// An interface to the embedding layer, which provides threading support.
+class AndroidThreading {
+public:
+    static void scheduleDispatchFunctionsOnMainThread();
+};
+
+} // namespace WTF
+
+#endif // AndroidThreading_h
diff --git a/wtf/android/MainThreadAndroid.cpp b/wtf/android/MainThreadAndroid.cpp
new file mode 100644 (file)
index 0000000..5e5f7b1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+#include "AndroidThreading.h"
+
+namespace WTF {
+
+void initializeMainThreadPlatform()
+{
+}
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+    AndroidThreading::scheduleDispatchFunctionsOnMainThread();
+}
+
+} // namespace WTF
index e9b1f3900aaa8a24c29f34418bfb4958d229977c..b2c507563432616e03384f66a4bd16b146557ecb 100644 (file)
 
 namespace WTF {
 
 
 namespace WTF {
 
-    // An interface to the embedding layer, which provides threading support.
-    class ChromiumThreading {
-    public:
-        static void initializeMainThread();
-        static void scheduleDispatchFunctionsOnMainThread();
-    };
+// An interface to the embedding layer, which provides threading support.
+class ChromiumThreading {
+public:
+    static void initializeMainThread();
+    static void scheduleDispatchFunctionsOnMainThread();
+};
 
 } // namespace WTF
 
 
 } // namespace WTF
 
index d75c17a9338daad47395023a10ebaa6eb2a62444..6289d0464cb6b16df8a8eeb6d545146de9ebc898 100644 (file)
 #else
 #define NO_ERRNO
 #endif
 #else
 #define NO_ERRNO
 #endif
-#include <float.h>
 #include <math.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <math.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <wtf/AlwaysInline.h>
 #include <wtf/Assertions.h>
 #include <wtf/FastMalloc.h>
 #include <wtf/AlwaysInline.h>
 #include <wtf/Assertions.h>
 #include <wtf/FastMalloc.h>
+#include <wtf/MathExtras.h>
 #include <wtf/Vector.h>
 #include <wtf/Threading.h>
 
 #include <wtf/Vector.h>
 #include <wtf/Threading.h>
 
 #pragma warning(disable: 4554)
 #endif
 
 #pragma warning(disable: 4554)
 #endif
 
-#if PLATFORM(BIG_ENDIAN)
+#if CPU(BIG_ENDIAN)
 #define IEEE_MC68k
 #define IEEE_MC68k
-#elif PLATFORM(MIDDLE_ENDIAN)
+#elif CPU(MIDDLE_ENDIAN)
 #define IEEE_ARM
 #else
 #define IEEE_8087
 #define IEEE_ARM
 #else
 #define IEEE_8087
@@ -262,7 +262,8 @@ typedef union { double d; uint32_t L[2]; } U;
 #define Pack_32
 #endif
 
 #define Pack_32
 #endif
 
-#if PLATFORM(PPC64) || PLATFORM(X86_64)
+#if CPU(PPC64) || CPU(X86_64)
+// FIXME: should we enable this on all 64-bit CPUs?
 // 64-bit emulation provided by the compiler is likely to be slower than dtoa own code on 32-bit hardware.
 #define USE_LONG_LONG
 #endif
 // 64-bit emulation provided by the compiler is likely to be slower than dtoa own code on 32-bit hardware.
 #define USE_LONG_LONG
 #endif
@@ -560,7 +561,7 @@ static void mult(BigInt& aRef, const BigInt& bRef)
     aRef = c;
 }
 
     aRef = c;
 }
 
-struct P5Node {
+struct P5Node : Noncopyable {
     BigInt val;
     P5Node* next;
 };
     BigInt val;
     P5Node* next;
 };
@@ -1869,7 +1870,7 @@ static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
  *       calculation.
  */
 
  *       calculation.
  */
 
-void dtoa(char* result, double dd, int ndigits, int* decpt, int* sign, char** rve)
+void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char** rve)
 {
     /*
         Arguments ndigits, decpt, sign are similar to those
 {
     /*
         Arguments ndigits, decpt, sign are similar to those
@@ -1908,16 +1909,23 @@ void dtoa(char* result, double dd, int ndigits, int* decpt, int* sign, char** rv
     {
         /* Infinity or NaN */
         *decpt = 9999;
     {
         /* Infinity or NaN */
         *decpt = 9999;
-        if (!word1(&u) && !(word0(&u) & 0xfffff))
+        if (!word1(&u) && !(word0(&u) & 0xfffff)) {
             strcpy(result, "Infinity");
             strcpy(result, "Infinity");
-        else 
+            if (rve)
+                *rve = result + 8;
+        } else {
             strcpy(result, "NaN");
             strcpy(result, "NaN");
+            if (rve)
+                *rve = result + 3;
+        }
         return;
     }
     if (!dval(&u)) {
         *decpt = 1;
         result[0] = '0';
         result[1] = '\0';
         return;
     }
     if (!dval(&u)) {
         *decpt = 1;
         result[0] = '0';
         result[1] = '\0';
+        if (rve)
+            *rve = result + 1;
         return;
     }
 
         return;
     }
 
@@ -2376,4 +2384,83 @@ ret:
         *rve = s;
 }
 
         *rve = s;
 }
 
+static ALWAYS_INLINE void append(char*& next, const char* src, unsigned size)
+{
+    for (unsigned i = 0; i < size; ++i)
+        *next++ = *src++;
+}
+
+void doubleToStringInJavaScriptFormat(double d, DtoaBuffer buffer, unsigned* resultLength)
+{
+    ASSERT(buffer);
+
+    // avoid ever printing -NaN, in JS conceptually there is only one NaN value
+    if (isnan(d)) {
+        append(buffer, "NaN", 3);
+        if (resultLength)
+            *resultLength = 3;
+        return;
+    }
+    // -0 -> "0"
+    if (!d) {
+        buffer[0] = '0';
+        if (resultLength)
+            *resultLength = 1;
+        return;
+    }
+
+    int decimalPoint;
+    int sign;
+
+    DtoaBuffer result;
+    char* resultEnd = 0;
+    WTF::dtoa(result, d, 0, &decimalPoint, &sign, &resultEnd);
+    int length = resultEnd - result;
+
+    char* next = buffer;
+    if (sign)
+        *next++ = '-';
+
+    if (decimalPoint <= 0 && decimalPoint > -6) {
+        *next++ = '0';
+        *next++ = '.';
+        for (int j = decimalPoint; j < 0; j++)
+            *next++ = '0';
+        append(next, result, length);
+    } else if (decimalPoint <= 21 && decimalPoint > 0) {
+        if (length <= decimalPoint) {
+            append(next, result, length);
+            for (int j = 0; j < decimalPoint - length; j++)
+                *next++ = '0';
+        } else {
+            append(next, result, decimalPoint);
+            *next++ = '.';
+            append(next, result + decimalPoint, length - decimalPoint);
+        }
+    } else if (result[0] < '0' || result[0] > '9')
+        append(next, result, length);
+    else {
+        *next++ = result[0];
+        if (length > 1) {
+            *next++ = '.';
+            append(next, result + 1, length - 1);
+        }
+
+        *next++ = 'e';
+        *next++ = (decimalPoint >= 0) ? '+' : '-';
+        // decimalPoint can't be more than 3 digits decimal given the
+        // nature of float representation
+        int exponential = decimalPoint - 1;
+        if (exponential < 0)
+            exponential = -exponential;
+        if (exponential >= 100)
+            *next++ = static_cast<char>('0' + exponential / 100);
+        if (exponential >= 10)
+            *next++ = static_cast<char>('0' + (exponential % 100) / 10);
+        *next++ = static_cast<char>('0' + exponential % 10);
+    }
+    if (resultLength)
+        *resultLength = next - buffer;
+}
+
 } // namespace WTF
 } // namespace WTF
index cbec7c71827cf1f857592e3dc796e392ac10a22e..6127f53972a3180bd3b8c03c7ed3768bb9b26338 100644 (file)
@@ -30,8 +30,18 @@ namespace WTF {
     extern WTF::Mutex* s_dtoaP5Mutex;
 
     double strtod(const char* s00, char** se);
     extern WTF::Mutex* s_dtoaP5Mutex;
 
     double strtod(const char* s00, char** se);
-    void dtoa(char* result, double d, int ndigits, int* decpt, int* sign, char** rve);
+
+    typedef char DtoaBuffer[80];
+    void dtoa(DtoaBuffer result, double d, int ndigits, int* decpt, int* sign, char** rve);
+
+    // dtoa() for ECMA-262 'ToString Applied to the Number Type.'
+    // The *resultLength will have the length of the resultant string in bufer.
+    // The resultant string isn't terminated by 0.
+    void doubleToStringInJavaScriptFormat(double, DtoaBuffer, unsigned* resultLength);
 
 } // namespace WTF
 
 
 } // namespace WTF
 
+using WTF::DtoaBuffer;
+using WTF::doubleToStringInJavaScriptFormat;
+
 #endif // WTF_dtoa_h
 #endif // WTF_dtoa_h
diff --git a/wtf/gtk/GOwnPtr.cpp b/wtf/gtk/GOwnPtr.cpp
new file mode 100644 (file)
index 0000000..1a151b9
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "GOwnPtr.h"
+
+#include <glib.h>
+
+namespace WTF {
+
+template <> void freeOwnedGPtr<GError>(GError* ptr)
+{
+    if (ptr)
+        g_error_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GList>(GList* ptr)
+{
+    g_list_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GCond>(GCond* ptr)
+{
+    if (ptr)
+        g_cond_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GMutex>(GMutex* ptr)
+{
+    if (ptr)
+        g_mutex_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GPatternSpec>(GPatternSpec* ptr)
+{
+    if (ptr)
+        g_pattern_spec_free(ptr);
+}
+
+template <> void freeOwnedGPtr<GDir>(GDir* ptr)
+{
+    if (ptr)
+        g_dir_close(ptr);
+}
+} // namespace WTF
diff --git a/wtf/gtk/GOwnPtr.h b/wtf/gtk/GOwnPtr.h
new file mode 100644 (file)
index 0000000..ad2c30e
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ *  Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008 Collabora Ltd.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOwnPtr_h
+#define GOwnPtr_h
+
+#include <algorithm>
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+
+// Forward delcarations at this point avoid the need to include GLib includes
+// in WTF headers.
+typedef struct _GError GError;
+typedef struct _GList GList;
+typedef struct _GCond GCond;
+typedef struct _GMutex GMutex;
+typedef struct _GPatternSpec GPatternSpec;
+typedef struct _GDir GDir;
+typedef struct _GHashTable GHashTable;
+extern "C" void g_free(void*);
+
+namespace WTF {
+
+template <typename T> inline void freeOwnedGPtr(T* ptr);
+template<> void freeOwnedGPtr<GError>(GError*);
+template<> void freeOwnedGPtr<GList>(GList*);
+template<> void freeOwnedGPtr<GCond>(GCond*);
+template<> void freeOwnedGPtr<GMutex>(GMutex*);
+template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*);
+template<> void freeOwnedGPtr<GDir>(GDir*);
+template<> void freeOwnedGPtr<GHashTable>(GHashTable*);
+
+template <typename T> class GOwnPtr : public Noncopyable {
+public:
+    explicit GOwnPtr(T* ptr = 0) : m_ptr(ptr) { }
+    ~GOwnPtr() { freeOwnedGPtr(m_ptr); }
+
+    T* get() const { return m_ptr; }
+    T* release()
+    {
+        T* ptr = m_ptr;
+        m_ptr = 0;
+        return ptr;
+    }
+
+    T*& outPtr()
+    {
+        ASSERT(!m_ptr);
+        return m_ptr;
+    }
+
+    void set(T* ptr)
+    {
+        ASSERT(!ptr || m_ptr != ptr);
+        freeOwnedGPtr(m_ptr);
+        m_ptr = ptr;
+    }
+
+    void clear()
+    {
+        freeOwnedGPtr(m_ptr);
+        m_ptr = 0;
+    }
+
+    T& operator*() const
+    {
+        ASSERT(m_ptr);
+        return *m_ptr;
+    }
+
+    T* operator->() const
+    {
+        ASSERT(m_ptr);
+        return m_ptr;
+    }
+
+    bool operator!() const { return !m_ptr; }
+
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
+    typedef T* GOwnPtr::*UnspecifiedBoolType;
+    operator UnspecifiedBoolType() const { return m_ptr ? &GOwnPtr::m_ptr : 0; }
+
+    void swap(GOwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
+
+private:
+    T* m_ptr;
+};
+
+template <typename T> inline void swap(GOwnPtr<T>& a, GOwnPtr<T>& b)
+{
+    a.swap(b);
+}
+
+template <typename T, typename U> inline bool operator==(const GOwnPtr<T>& a, U* b)
+{ 
+    return a.get() == b; 
+}
+
+template <typename T, typename U> inline bool operator==(T* a, const GOwnPtr<U>& b) 
+{
+    return a == b.get(); 
+}
+
+template <typename T, typename U> inline bool operator!=(const GOwnPtr<T>& a, U* b)
+{
+    return a.get() != b; 
+}
+
+template <typename T, typename U> inline bool operator!=(T* a, const GOwnPtr<U>& b)
+{ 
+    return a != b.get(); 
+}
+
+template <typename T> inline typename GOwnPtr<T>::PtrType getPtr(const GOwnPtr<T>& p)
+{
+    return p.get();
+}
+
+template <typename T> inline void freeOwnedGPtr(T* ptr)
+{
+    g_free(ptr);
+}
+
+} // namespace WTF
+
+using WTF::GOwnPtr;
+
+#endif // GOwnPtr_h
diff --git a/wtf/gtk/GRefPtr.cpp b/wtf/gtk/GRefPtr.cpp
new file mode 100644 (file)
index 0000000..e7cf34b
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 Martin Robinson
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "GRefPtr.h"
+
+#include <glib.h>
+
+namespace WTF {
+
+template <> GHashTable* refGPtr(GHashTable* ptr)
+{
+    if (ptr)
+        g_hash_table_ref(ptr);
+    return ptr;
+}
+
+template <> void derefGPtr(GHashTable* ptr)
+{
+    g_hash_table_unref(ptr);
+}
+
+} // namespace WTF
diff --git a/wtf/gtk/GRefPtr.h b/wtf/gtk/GRefPtr.h
new file mode 100644 (file)
index 0000000..66739ef
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008 Collabora Ltd.
+ *  Copyright (C) 2009 Martin Robinson
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WTF_GRefPtr_h
+#define WTF_GRefPtr_h
+
+#include "AlwaysInline.h"
+#include <algorithm>
+
+typedef struct _GHashTable GHashTable;
+
+namespace WTF {
+
+enum GRefPtrAdoptType { GRefPtrAdopt };
+template <typename T> inline T* refGPtr(T*);
+template <typename T> inline void derefGPtr(T*);
+template <typename T> class GRefPtr;
+template <typename T> GRefPtr<T> adoptGRef(T*);
+template <> GHashTable* refGPtr(GHashTable* ptr);
+template <> void derefGPtr(GHashTable* ptr);
+
+template <typename T> class GRefPtr {
+public:
+    GRefPtr() : m_ptr(0) { }
+    GRefPtr(T* ptr) : m_ptr(ptr) { if (ptr) refGPtr(ptr); }
+    GRefPtr(const GRefPtr& o) : m_ptr(o.m_ptr) { if (T* ptr = m_ptr) refGPtr(ptr); }
+    template <typename U> GRefPtr(const GRefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) refGPtr(ptr); }
+
+    ~GRefPtr() { if (T* ptr = m_ptr) derefGPtr(ptr); }
+
+    void clear()
+    {
+        if (T* ptr = m_ptr)
+            derefGPtr(ptr);
+        m_ptr = 0;
+    }
+
+    T* get() const { return m_ptr; }
+    T& operator*() const { return *m_ptr; }
+    ALWAYS_INLINE T* operator->() const { return m_ptr; }
+
+    bool operator!() const { return !m_ptr; }
+
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
+    typedef T* GRefPtr::*UnspecifiedBoolType;
+    operator UnspecifiedBoolType() const { return m_ptr ? &GRefPtr::m_ptr : 0; }
+
+    GRefPtr& operator=(const GRefPtr&);
+    GRefPtr& operator=(T*);
+    template <typename U> GRefPtr& operator=(const GRefPtr<U>&);
+
+    void swap(GRefPtr&);
+    friend GRefPtr adoptGRef<T>(T*);
+
+private:
+    static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
+    // Adopting constructor.
+    GRefPtr(T* ptr, GRefPtrAdoptType) : m_ptr(ptr) {}
+
+    T* m_ptr;
+};
+
+template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(const GRefPtr<T>& o)
+{
+    T* optr = o.get();
+    if (optr)
+        refGPtr(optr);
+    T* ptr = m_ptr;
+    m_ptr = optr;
+    if (ptr)
+        derefGPtr(ptr);
+    return *this;
+}
+
+template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(T* optr)
+{
+    T* ptr = m_ptr;
+    if (optr)
+        refGPtr(optr);
+    m_ptr = optr;
+    if (ptr)
+        derefGPtr(ptr);
+    return *this;
+}
+
+template <class T> inline void GRefPtr<T>::swap(GRefPtr<T>& o)
+{
+    std::swap(m_ptr, o.m_ptr);
+}
+
+template <class T> inline void swap(GRefPtr<T>& a, GRefPtr<T>& b)
+{
+    a.swap(b);
+}
+
+template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, const GRefPtr<U>& b)
+{
+    return a.get() == b.get();
+}
+
+template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, U* b)
+{
+    return a.get() == b;
+}
+
+template <typename T, typename U> inline bool operator==(T* a, const GRefPtr<U>& b)
+{
+    return a == b.get();
+}
+
+template <typename T, typename U> inline bool operator!=(const GRefPtr<T>& a, const GRefPtr<U>& b)
+{
+    return a.get() != b.get();
+}
+
+template <typename T, typename U> inline bool operator!=(const GRefPtr<T>& a, U* b)
+{
+    return a.get() != b;
+}
+
+template <typename T, typename U> inline bool operator!=(T* a, const GRefPtr<U>& b)
+{
+    return a != b.get();
+}
+
+template <typename T, typename U> inline GRefPtr<T> static_pointer_cast(const GRefPtr<U>& p)
+{
+    return GRefPtr<T>(static_cast<T*>(p.get()));
+}
+
+template <typename T, typename U> inline GRefPtr<T> const_pointer_cast(const GRefPtr<U>& p)
+{
+    return GRefPtr<T>(const_cast<T*>(p.get()));
+}
+
+template <typename T> inline T* getPtr(const GRefPtr<T>& p)
+{
+    return p.get();
+}
+
+template <typename T> GRefPtr<T> adoptGRef(T* p)
+{
+    return GRefPtr<T>(p, GRefPtrAdopt);
+}
+
+template <typename T> inline T* refGPtr(T* ptr)
+{
+    if (ptr)
+        g_object_ref_sink(ptr);
+    return ptr;
+}
+
+template <typename T> inline void derefGPtr(T* ptr)
+{
+    if (ptr)
+        g_object_unref(ptr);
+}
+
+} // namespace WTF
+
+using WTF::GRefPtr;
+using WTF::refGPtr;
+using WTF::derefGPtr;
+using WTF::adoptGRef;
+using WTF::static_pointer_cast;
+using WTF::const_pointer_cast;
+
+#endif // WTF_GRefPtr_h
index b4f4de1a7d342cb4001881ce598b70057683a80c..a6ec8f75cbd7e7f907832a673584b9553d12ff88 100644 (file)
@@ -138,7 +138,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
     return threadID;
 }
 
     return threadID;
 }
 
-void setThreadNameInternal(const char*)
+void initializeCurrentThreadInternal(const char*)
 {
 }
 
 {
 }
 
diff --git a/wtf/haiku/MainThreadHaiku.cpp b/wtf/haiku/MainThreadHaiku.cpp
new file mode 100644 (file)
index 0000000..10c4248
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Kevin Ollivier
+ * Copyright (C) 2009 Maxime Simon
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MainThread.h"
+
+#include "NotImplemented.h"
+
+namespace WTF {
+
+void initializeMainThreadPlatform()
+{
+    notImplemented();
+}
+
+void scheduleDispatchFunctionsOnMainThread()
+{
+    notImplemented();
+}
+
+} // namespace WTF
+
diff --git a/wtf/iphone/MainThreadIPhone.mm b/wtf/iphone/MainThreadIPhone.mm
deleted file mode 100644 (file)
index 3b84fc3..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution. 
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#import "config.h"
-#import "MainThread.h"
-
-#import <Foundation/NSThread.h>
-#import <wtf/Assertions.h>
-
-@interface WTFMainThreadCaller : NSObject {
-}
-- (void)call;
-@end
-
-@implementation WTFMainThreadCaller
-
-- (void)call
-{
-    WTF::dispatchFunctionsFromMainThread();
-}
-
-@end // implementation WTFMainThreadCaller
-
-namespace WTF {
-
-static NSThread* staticMainNSThread = nil;
-static WTFMainThreadCaller* staticMainThreadCaller = nil;
-
-void initializeMainThreadPlatform()
-{
-    ASSERT(!staticMainThreadCaller);
-    staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
-    ASSERT(!staticMainNSThread);
-    staticMainNSThread = [[NSThread currentThread] retain];
-}
-
-void scheduleDispatchFunctionsOnMainThread()
-{
-    ASSERT(staticMainNSThread);
-    ASSERT(staticMainThreadCaller);
-    [staticMainThreadCaller performSelector:@selector(call) onThread:staticMainNSThread withObject:nil waitUntilDone:NO];
-}
-
-} // namespace WTF
diff --git a/wtf/iphone/WebCoreThread.cpp b/wtf/iphone/WebCoreThread.cpp
new file mode 100644 (file)
index 0000000..9c1f8e6
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "WebCoreThread.h"
+
+bool (*WebCoreWebThreadIsLockedOrDisabled)(void);
diff --git a/wtf/iphone/WebCoreThread.h b/wtf/iphone/WebCoreThread.h
new file mode 100644 (file)
index 0000000..f397dfc
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Since this is a shared header, with the same file name as a file in
+// WebCore we prefix this with JavaScriptCore to make it unique.
+#ifndef JavaScriptCore_WebCoreThread_h
+#define JavaScriptCore_WebCoreThread_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern bool (*WebCoreWebThreadIsLockedOrDisabled)(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index c79acc16f817362b0ae3b055b24dfa6119d18242..0ddd5f64ea28a0726792c9ebabf8385c0f8250b5 100644 (file)
 namespace WTF {
 
 static WTFMainThreadCaller* staticMainThreadCaller = nil;
 namespace WTF {
 
 static WTFMainThreadCaller* staticMainThreadCaller = nil;
+#if USE(WEB_THREAD)
+static NSThread* webThread = nil;
+#endif
 
 void initializeMainThreadPlatform()
 {
     ASSERT(!staticMainThreadCaller);
     staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
 
 void initializeMainThreadPlatform()
 {
     ASSERT(!staticMainThreadCaller);
     staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
+
+#if USE(WEB_THREAD)
+    webThread = [[NSThread currentThread] retain];
+#endif
 }
 
 void scheduleDispatchFunctionsOnMainThread()
 {
     ASSERT(staticMainThreadCaller);
 }
 
 void scheduleDispatchFunctionsOnMainThread()
 {
     ASSERT(staticMainThreadCaller);
+#if USE(WEB_THREAD)
+    [staticMainThreadCaller performSelector:@selector(call) onThread:webThread withObject:nil waitUntilDone:NO];
+#else
     [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
     [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
+#endif
 }
 
 } // namespace WTF
 }
 
 } // namespace WTF
index 1fdd2bbb9cb672823d07fdc95461dc5b627c1c33..dc04a684c35974aa569737d3e7d56b46d0066fe6 100644 (file)
@@ -29,6 +29,8 @@
 #include "config.h"
 #include "Threading.h"
 
 #include "config.h"
 #include "Threading.h"
 
+#if !ENABLE(SINGLE_THREADED)
+
 #include "CurrentTime.h"
 #include "HashMap.h"
 #include "MainThread.h"
 #include "CurrentTime.h"
 #include "HashMap.h"
 #include "MainThread.h"
@@ -64,6 +66,21 @@ void ThreadPrivate::run()
     m_returnValue = m_entryPoint(m_data);
 }
 
     m_returnValue = m_entryPoint(m_data);
 }
 
+class ThreadMonitor : public QObject {
+    Q_OBJECT
+public:
+    static ThreadMonitor * instance()
+    {
+        static ThreadMonitor *instance = new ThreadMonitor();
+        return instance;
+    }
+
+public Q_SLOTS:
+    void threadFinished()
+    {
+        sender()->deleteLater();
+    }
+};
 
 static Mutex* atomicallyInitializedStaticMutex;
 
 
 static Mutex* atomicallyInitializedStaticMutex;
 
@@ -155,6 +172,9 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
         LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
         return 0;
     }
         LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
         return 0;
     }
+
+    QObject::connect(thread, SIGNAL(finished()), ThreadMonitor::instance(), SLOT(threadFinished()));
+
     thread->start();
 
     QThread* threadRef = static_cast<QThread*>(thread);
     thread->start();
 
     QThread* threadRef = static_cast<QThread*>(thread);
@@ -162,7 +182,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
     return establishIdentifierForThread(threadRef);
 }
 
     return establishIdentifierForThread(threadRef);
 }
 
-void setThreadNameInternal(const char*)
+void initializeCurrentThreadInternal(const char*)
 {
 }
 
 {
 }
 
@@ -181,8 +201,10 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
     return !res;
 }
 
     return !res;
 }
 
-void detachThread(ThreadIdentifier)
+void detachThread(ThreadIdentifier threadID)
 {
 {
+    ASSERT(threadID);
+    clearThreadForIdentifier(threadID);
 }
 
 ThreadIdentifier currentThread()
 }
 
 ThreadIdentifier currentThread()
@@ -267,3 +289,7 @@ void ThreadCondition::broadcast()
 }
 
 } // namespace WebCore
 }
 
 } // namespace WebCore
+
+#include "ThreadingQt.moc"
+
+#endif
index f04779dd7d356150c17270e443b822ab26196ed5..51e8a063f2323ab1044abff70a4eae8834402fcc 100644 (file)
@@ -39,7 +39,7 @@ struct UCollator;
 
 namespace WTF {
 
 
 namespace WTF {
 
-    class Collator : Noncopyable {
+    class Collator : public Noncopyable {
     public:
         enum Result { Equal = 0, Greater = 1, Less = -1 };
 
     public:
         enum Result { Equal = 0, Greater = 1, Less = -1 };
 
index 9e713fe36489fa8f46b724b4b1d838f94b28d72f..21d58563cc005ae61ac74f03966b57eec55d1027 100644 (file)
@@ -23,6 +23,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
+#include "config.h"
 #include "UTF8.h"
 
 namespace WTF {
 #include "UTF8.h"
 
 namespace WTF {
index f86a9b7c39a0f03aa012680969afa473e24f9ca5..d59439dc83634184801acd26f8f54584b03024a9 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2006 George Staikos <staikos@kde.org>
  *  Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
 /*
  *  Copyright (C) 2006 George Staikos <staikos@kde.org>
  *  Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007-2009 Torch Mobile, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -30,6 +31,8 @@
 #include <wtf/unicode/icu/UnicodeIcu.h>
 #elif USE(GLIB_UNICODE)
 #include <wtf/unicode/glib/UnicodeGLib.h>
 #include <wtf/unicode/icu/UnicodeIcu.h>
 #elif USE(GLIB_UNICODE)
 #include <wtf/unicode/glib/UnicodeGLib.h>
+#elif USE(WINCE_UNICODE)
+#include <wtf/unicode/wince/UnicodeWince.h>
 #else
 #error "Unknown Unicode implementation"
 #endif
 #else
 #error "Unknown Unicode implementation"
 #endif
index a779b36809d1e116b1198ee18f8ca5cb46f4a302..e20c376e4404fcd29d31d95da22a6f257b17f25c 100644 (file)
@@ -19,6 +19,7 @@
  *
  */
 
  *
  */
 
+#include "config.h"
 #include "UnicodeGLib.h"
 
 namespace WTF {
 #include "UnicodeGLib.h"
 
 namespace WTF {
index c03d3ec3b194897e053227c5e0d674ca6e211660..d72e707abcd46c9494480835b8d722aed4c84424 100644 (file)
@@ -26,7 +26,7 @@
 #define UnicodeGLib_h
 
 #include "UnicodeMacrosFromICU.h"
 #define UnicodeGLib_h
 
 #include "UnicodeMacrosFromICU.h"
-#include <wtf/GOwnPtr.h>
+#include <wtf/gtk/GOwnPtr.h>
 
 #include <glib.h>
 #include <pango/pango.h>
 
 #include <glib.h>
 #include <pango/pango.h>
@@ -152,6 +152,11 @@ inline bool isArabicChar(UChar32 c)
     return c >= 0x0600 && c <= 0x06FF;
 }
 
     return c >= 0x0600 && c <= 0x06FF;
 }
 
+inline bool isAlphanumeric(UChar32 c)
+{
+    return g_unichar_isalnum(c);
+}
+
 inline bool isFormatChar(UChar32 c)
 {
     return g_unichar_type(c) == G_UNICODE_FORMAT;
 inline bool isFormatChar(UChar32 c)
 {
     return g_unichar_type(c) == G_UNICODE_FORMAT;
index 79dec79d24a249b9039d74046ed509ec09480130..a1753a4c096f0502aed3cc75c4c2290dffed6fc0 100644 (file)
@@ -36,7 +36,8 @@
 #include <unicode/ucol.h>
 #include <string.h>
 
 #include <unicode/ucol.h>
 #include <string.h>
 
-#if PLATFORM(DARWIN)
+#if OS(DARWIN)
+#include "RetainPtr.h"
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
@@ -58,13 +59,18 @@ Collator::Collator(const char* locale)
 
 std::auto_ptr<Collator> Collator::userDefault()
 {
 
 std::auto_ptr<Collator> Collator::userDefault()
 {
-#if PLATFORM(DARWIN) && PLATFORM(CF)
+#if OS(DARWIN) && PLATFORM(CF)
     // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work.
     // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work.
-    CFStringRef collationOrder = (CFStringRef)CFPreferencesCopyValue(CFSTR("AppleCollationOrder"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !OS(IPHONE_OS)
+    RetainPtr<CFLocaleRef> currentLocale(AdoptCF, CFLocaleCopyCurrent());
+    CFStringRef collationOrder = (CFStringRef)CFLocaleGetValue(currentLocale.get(), kCFLocaleCollatorIdentifier);
+#else
+    RetainPtr<CFStringRef> collationOrderRetainer(AdoptCF, (CFStringRef)CFPreferencesCopyValue(CFSTR("AppleCollationOrder"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost));
+    CFStringRef collationOrder = collationOrderRetainer.get();
+#endif
     char buf[256];
     if (collationOrder) {
         CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII);
     char buf[256];
     if (collationOrder) {
         CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII);
-        CFRelease(collationOrder);
         return std::auto_ptr<Collator>(new Collator(buf));
     } else
         return std::auto_ptr<Collator>(new Collator(""));
         return std::auto_ptr<Collator>(new Collator(buf));
     } else
         return std::auto_ptr<Collator>(new Collator(""));
index 35c6fbfd7b1b0ba1b3dcddd42750447d5bac059d..a2a5c0a57674add15a47e884865118278cf32760 100644 (file)
@@ -164,6 +164,11 @@ inline bool isArabicChar(UChar32 c)
       return ublock_getCode(c) == UBLOCK_ARABIC;
 }
 
       return ublock_getCode(c) == UBLOCK_ARABIC;
 }
 
+inline bool isAlphanumeric(UChar32 c)
+{
+    return u_isalnum(c);
+}
+
 inline bool isSeparatorSpace(UChar32 c)
 {
     return u_charType(c) == U_SPACE_SEPARATOR;
 inline bool isSeparatorSpace(UChar32 c)
 {
     return u_charType(c) == U_SPACE_SEPARATOR;
index 1531694432f7ff8e7f6adec2ec7db856ba171bb9..cfd482d995363cef83452ab220164ef6f47e0e2e 100644 (file)
@@ -30,7 +30,6 @@
 
 #include <stdint.h>
 
 
 #include <stdint.h>
 
-#if QT_VERSION >= 0x040300
 QT_BEGIN_NAMESPACE
 namespace QUnicodeTables {
     struct Properties {
 QT_BEGIN_NAMESPACE
 namespace QUnicodeTables {
     struct Properties {
@@ -55,10 +54,9 @@ namespace QUnicodeTables {
     Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2);
 }
 QT_END_NAMESPACE
     Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2);
 }
 QT_END_NAMESPACE
-#endif
 
 // ugly hack to make UChar compatible with JSChar in API/JSStringRef.h
 
 // ugly hack to make UChar compatible with JSChar in API/JSStringRef.h
-#if defined(Q_OS_WIN)
+#if defined(Q_OS_WIN) || COMPILER(WINSCW)
 typedef wchar_t UChar;
 #else
 typedef uint16_t UChar;
 typedef wchar_t UChar;
 #else
 typedef uint16_t UChar;
@@ -186,8 +184,6 @@ enum CharCategory {
 };
 
 
 };
 
 
-#if QT_VERSION >= 0x040300
-
 // FIXME: handle surrogates correctly in all methods
 
 inline UChar32 toLower(UChar32 ch)
 // FIXME: handle surrogates correctly in all methods
 
 inline UChar32 toLower(UChar32 ch)
@@ -406,138 +402,6 @@ inline CharCategory category(UChar32 c)
     return (CharCategory) U_MASK(QChar::category(c));
 }
 
     return (CharCategory) U_MASK(QChar::category(c));
 }
 
-#else
-
-inline UChar32 toLower(UChar32 ch)
-{
-    if (ch > 0xffff)
-        return ch;
-    return QChar((unsigned short)ch).toLower().unicode();
-}
-
-inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
-{
-  *error = false;
-  if (resultLength < srcLength) {
-    *error = true;
-    return srcLength;
-  }
-  for (int i = 0; i < srcLength; ++i)
-    result[i] = QChar(src[i]).toLower().unicode();
-  return srcLength;
-}
-
-inline UChar32 toUpper(UChar32 ch)
-{
-    if (ch > 0xffff)
-        return ch;
-    return QChar((unsigned short)ch).toUpper().unicode();
-}
-
-inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
-{
-    *error = false;
-    if (resultLength < srcLength) {
-        *error = true;
-        return srcLength;
-    }
-    for (int i = 0; i < srcLength; ++i)
-        result[i] = QChar(src[i]).toUpper().unicode();
-    return srcLength;
-}
-
-inline int toTitleCase(UChar32 c)
-{
-    if (c > 0xffff)
-        return c;
-    return QChar((unsigned short)c).toUpper().unicode();
-}
-
-inline UChar32 foldCase(UChar32 c)
-{
-    if (c > 0xffff)
-        return c;
-    return QChar((unsigned short)c).toLower().unicode();
-}
-
-inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
-{
-    return toLower(result, resultLength, src, srcLength, error);
-}
-
-inline bool isPrintableChar(UChar32 c)
-{
-    return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPrint();
-}
-
-inline bool isArabicChar(UChar32 c)
-{
-    return c >= 0x0600 && c <= 0x06FF;
-}
-
-inline bool isSeparatorSpace(UChar32 c)
-{
-    return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Separator_Space;
-}
-
-inline bool isPunct(UChar32 c)
-{
-    return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPunct();
-}
-
-inline bool isLower(UChar32 c)
-{
-    return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Letter_Lowercase;
-}
-
-inline UChar32 mirroredChar(UChar32 c)
-{
-    if (c > 0xffff)
-        return c;
-    return QChar(c).mirroredChar().unicode();
-}
-
-inline uint8_t combiningClass(UChar32 c)
-{
-    if (c > 0xffff)
-        return 0;
-    return QChar((unsigned short)c).combiningClass();
-}
-
-inline DecompositionType decompositionType(UChar32 c)
-{
-    if (c > 0xffff)
-        return DecompositionNone;
-    return (DecompositionType)QChar(c).decompositionTag();
-}
-
-inline int umemcasecmp(const UChar* a, const UChar* b, int len)
-{
-    for (int i = 0; i < len; ++i) {
-        QChar c1 = QChar(a[i]).toLower();
-        QChar c2 = QChar(b[i]).toLower();
-        if (c1 != c2)
-        return c1.unicode() - c2.unicode();
-    }
-    return 0;
-}
-
-inline Direction direction(UChar32 c)
-{
-    if (c > 0xffff)
-        return LeftToRight;
-    return (Direction)QChar(c).direction();
-}
-
-inline CharCategory category(UChar32 c)
-{
-    if (c > 0xffff)
-        return NoCategory;
-    return (CharCategory) U_MASK(QChar(c).category());
-}
-
-#endif
-
 } }
 
 #endif // WTF_UNICODE_QT4_H
 } }
 
 #endif // WTF_UNICODE_QT4_H
diff --git a/wtf/unicode/wince/UnicodeWince.cpp b/wtf/unicode/wince/UnicodeWince.cpp
new file mode 100644 (file)
index 0000000..2df44f8
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ *  Copyright (C) 2006 George Staikos <staikos@kde.org>
+ *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
+ *  Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "UnicodeWince.h"
+
+#include <wchar.h>
+
+namespace WTF {
+namespace Unicode {
+
+wchar_t toLower(wchar_t c)
+{
+    return towlower(c);
+}
+
+wchar_t toUpper(wchar_t c)
+{
+    return towupper(c);
+}
+
+wchar_t foldCase(wchar_t c)
+{
+    return towlower(c);
+}
+
+bool isPrintableChar(wchar_t c)
+{
+    return !!iswprint(c);
+}
+
+bool isSpace(wchar_t c)
+{
+    return !!iswspace(c);
+}
+
+bool isLetter(wchar_t c)
+{
+    return !!iswalpha(c);
+}
+
+bool isUpper(wchar_t c)
+{
+    return !!iswupper(c);
+}
+
+bool isLower(wchar_t c)
+{
+    return !!iswlower(c);
+}
+
+bool isDigit(wchar_t c)
+{
+    return !!iswdigit(c);
+}
+
+bool isPunct(wchar_t c)
+{
+    return !!iswpunct(c);
+}
+
+int toLower(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError)
+{
+    const UChar* sourceIterator = source;
+    const UChar* sourceEnd = source + sourceLength;
+    UChar* resultIterator = result;
+    UChar* resultEnd = result + resultLength;
+
+    int remainingCharacters = 0;
+    if (sourceLength <= resultLength)
+        while (sourceIterator < sourceEnd)
+            *resultIterator++ = towlower(*sourceIterator++);
+    else
+        while (resultIterator < resultEnd)
+            *resultIterator++ = towlower(*sourceIterator++);
+
+    if (sourceIterator < sourceEnd)
+        remainingCharacters += sourceEnd - sourceIterator;
+    *isError = (remainingCharacters != 0);
+    if (resultIterator < resultEnd)
+        *resultIterator = 0;
+
+    return (resultIterator - result) + remainingCharacters;
+}
+
+int toUpper(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError)
+{
+    const UChar* sourceIterator = source;
+    const UChar* sourceEnd = source + sourceLength;
+    UChar* resultIterator = result;
+    UChar* resultEnd = result + resultLength;
+
+    int remainingCharacters = 0;
+    if (sourceLength <= resultLength)
+        while (sourceIterator < sourceEnd)
+            *resultIterator++ = towupper(*sourceIterator++);
+    else
+        while (resultIterator < resultEnd)
+            *resultIterator++ = towupper(*sourceIterator++);
+
+    if (sourceIterator < sourceEnd)
+        remainingCharacters += sourceEnd - sourceIterator;
+    *isError = (remainingCharacters != 0);
+    if (resultIterator < resultEnd)
+        *resultIterator = 0;
+
+    return (resultIterator - result) + remainingCharacters;
+}
+
+int foldCase(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError)
+{
+    *isError = false;
+    if (resultLength < sourceLength) {
+        *isError = true;
+        return sourceLength;
+    }
+    for (int i = 0; i < sourceLength; ++i)
+        result[i] = foldCase(source[i]);
+    return sourceLength;
+}
+
+wchar_t toTitleCase(wchar_t c)
+{
+    return towupper(c);
+}
+
+Direction direction(UChar32 c)
+{
+    return static_cast<Direction>(UnicodeCE::direction(c));
+}
+
+CharCategory category(unsigned int c)
+{
+    return static_cast<CharCategory>(TO_MASK((__int8) UnicodeCE::category(c)));
+}
+
+DecompositionType decompositionType(UChar32 c)
+{
+    return static_cast<DecompositionType>(UnicodeCE::decompositionType(c));
+}
+
+unsigned char combiningClass(UChar32 c)
+{
+    return UnicodeCE::combiningClass(c);
+}
+
+wchar_t mirroredChar(UChar32 c)
+{
+    return UnicodeCE::mirroredChar(c);
+}
+
+int digitValue(wchar_t c)
+{
+    return UnicodeCE::digitValue(c);
+}
+
+} // namespace Unicode
+} // namespace WTF
diff --git a/wtf/unicode/wince/UnicodeWince.h b/wtf/unicode/wince/UnicodeWince.h
new file mode 100644 (file)
index 0000000..db656ec
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ *  Copyright (C) 2006 George Staikos <staikos@kde.org>
+ *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
+ *  Copyright (C) 2007 Apple Computer, Inc. All rights reserved.
+ *  Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef UNICODE_WINCE_H
+#define UNICODE_WINCE_H
+
+#include "ce_unicode.h"
+
+#define TO_MASK(x) (1 << (x))
+
+// some defines from ICU needed one or two places
+
+#define U16_IS_LEAD(c) (((c) & 0xfffffc00) == 0xd800)
+#define U16_IS_TRAIL(c) (((c) & 0xfffffc00) == 0xdc00)
+#define U16_SURROGATE_OFFSET ((0xd800 << 10UL) + 0xdc00 - 0x10000)
+#define U16_GET_SUPPLEMENTARY(lead, trail) \
+    (((UChar32)(lead) << 10UL) + (UChar32)(trail) - U16_SURROGATE_OFFSET)
+
+#define U16_LEAD(supplementary) (UChar)(((supplementary) >> 10) + 0xd7c0)
+#define U16_TRAIL(supplementary) (UChar)(((supplementary) & 0x3ff) | 0xdc00)
+
+#define U_IS_SURROGATE(c) (((c) & 0xfffff800) == 0xd800)
+#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c)
+#define U16_IS_SURROGATE_LEAD(c) (((c) & 0x400) == 0)
+
+#define U16_NEXT(s, i, length, c) { \
+    (c)=(s)[(i)++]; \
+    if (U16_IS_LEAD(c)) { \
+        uint16_t __c2; \
+        if ((i) < (length) && U16_IS_TRAIL(__c2 = (s)[(i)])) { \
+            ++(i); \
+            (c) = U16_GET_SUPPLEMENTARY((c), __c2); \
+        } \
+    } \
+}
+
+#define U16_PREV(s, start, i, c) { \
+    (c)=(s)[--(i)]; \
+    if (U16_IS_TRAIL(c)) { \
+        uint16_t __c2; \
+        if ((i) > (start) && U16_IS_LEAD(__c2 = (s)[(i) - 1])) { \
+            --(i); \
+            (c) = U16_GET_SUPPLEMENTARY(__c2, (c)); \
+        } \
+    } \
+}
+
+#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c)
+
+namespace WTF {
+
+    namespace Unicode {
+
+        enum Direction {
+            LeftToRight = UnicodeCE::U_LEFT_TO_RIGHT,
+            RightToLeft = UnicodeCE::U_RIGHT_TO_LEFT,
+            EuropeanNumber = UnicodeCE::U_EUROPEAN_NUMBER,
+            EuropeanNumberSeparator = UnicodeCE::U_EUROPEAN_NUMBER_SEPARATOR,
+            EuropeanNumberTerminator = UnicodeCE::U_EUROPEAN_NUMBER_TERMINATOR,
+            ArabicNumber = UnicodeCE::U_ARABIC_NUMBER,
+            CommonNumberSeparator = UnicodeCE::U_COMMON_NUMBER_SEPARATOR,
+            BlockSeparator = UnicodeCE::U_BLOCK_SEPARATOR,
+            SegmentSeparator = UnicodeCE::U_SEGMENT_SEPARATOR,
+            WhiteSpaceNeutral = UnicodeCE::U_WHITE_SPACE_NEUTRAL,
+            OtherNeutral = UnicodeCE::U_OTHER_NEUTRAL,
+            LeftToRightEmbedding = UnicodeCE::U_LEFT_TO_RIGHT_EMBEDDING,
+            LeftToRightOverride = UnicodeCE::U_LEFT_TO_RIGHT_OVERRIDE,
+            RightToLeftArabic = UnicodeCE::U_RIGHT_TO_LEFT_ARABIC,
+            RightToLeftEmbedding = UnicodeCE::U_RIGHT_TO_LEFT_EMBEDDING,
+            RightToLeftOverride = UnicodeCE::U_RIGHT_TO_LEFT_OVERRIDE,
+            PopDirectionalFormat = UnicodeCE::U_POP_DIRECTIONAL_FORMAT,
+            NonSpacingMark = UnicodeCE::U_DIR_NON_SPACING_MARK,
+            BoundaryNeutral = UnicodeCE::U_BOUNDARY_NEUTRAL
+        };
+
+        enum DecompositionType {
+          DecompositionNone = UnicodeCE::U_DT_NONE,
+          DecompositionCanonical = UnicodeCE::U_DT_CANONICAL,
+          DecompositionCompat = UnicodeCE::U_DT_COMPAT,
+          DecompositionCircle = UnicodeCE::U_DT_CIRCLE,
+          DecompositionFinal = UnicodeCE::U_DT_FINAL,
+          DecompositionFont = UnicodeCE::U_DT_FONT,
+          DecompositionFraction = UnicodeCE::U_DT_FRACTION,
+          DecompositionInitial = UnicodeCE::U_DT_INITIAL,
+          DecompositionIsolated = UnicodeCE::U_DT_ISOLATED,
+          DecompositionMedial = UnicodeCE::U_DT_MEDIAL,
+          DecompositionNarrow = UnicodeCE::U_DT_NARROW,
+          DecompositionNoBreak = UnicodeCE::U_DT_NOBREAK,
+          DecompositionSmall = UnicodeCE::U_DT_SMALL,
+          DecompositionSquare = UnicodeCE::U_DT_SQUARE,
+          DecompositionSub = UnicodeCE::U_DT_SUB,
+          DecompositionSuper = UnicodeCE::U_DT_SUPER,
+          DecompositionVertical = UnicodeCE::U_DT_VERTICAL,
+          DecompositionWide = UnicodeCE::U_DT_WIDE,
+        };
+
+        enum CharCategory {
+          NoCategory =  0,
+          Other_NotAssigned = TO_MASK(UnicodeCE::U_GENERAL_OTHER_TYPES),
+          Letter_Uppercase = TO_MASK(UnicodeCE::U_UPPERCASE_LETTER),
+          Letter_Lowercase = TO_MASK(UnicodeCE::U_LOWERCASE_LETTER),
+          Letter_Titlecase = TO_MASK(UnicodeCE::U_TITLECASE_LETTER),
+          Letter_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_LETTER),
+          Letter_Other = TO_MASK(UnicodeCE::U_OTHER_LETTER),
+
+          Mark_NonSpacing = TO_MASK(UnicodeCE::U_NON_SPACING_MARK),
+          Mark_Enclosing = TO_MASK(UnicodeCE::U_ENCLOSING_MARK),
+          Mark_SpacingCombining = TO_MASK(UnicodeCE::U_COMBINING_SPACING_MARK),
+
+          Number_DecimalDigit = TO_MASK(UnicodeCE::U_DECIMAL_DIGIT_NUMBER),
+          Number_Letter = TO_MASK(UnicodeCE::U_LETTER_NUMBER),
+          Number_Other = TO_MASK(UnicodeCE::U_OTHER_NUMBER),
+
+          Separator_Space = TO_MASK(UnicodeCE::U_SPACE_SEPARATOR),
+          Separator_Line = TO_MASK(UnicodeCE::U_LINE_SEPARATOR),
+          Separator_Paragraph = TO_MASK(UnicodeCE::U_PARAGRAPH_SEPARATOR),
+
+          Other_Control = TO_MASK(UnicodeCE::U_CONTROL_CHAR),
+          Other_Format = TO_MASK(UnicodeCE::U_FORMAT_CHAR),
+          Other_PrivateUse = TO_MASK(UnicodeCE::U_PRIVATE_USE_CHAR),
+          Other_Surrogate = TO_MASK(UnicodeCE::U_SURROGATE),
+
+          Punctuation_Dash = TO_MASK(UnicodeCE::U_DASH_PUNCTUATION),
+          Punctuation_Open = TO_MASK(UnicodeCE::U_START_PUNCTUATION),
+          Punctuation_Close = TO_MASK(UnicodeCE::U_END_PUNCTUATION),
+          Punctuation_Connector = TO_MASK(UnicodeCE::U_CONNECTOR_PUNCTUATION),
+          Punctuation_Other = TO_MASK(UnicodeCE::U_OTHER_PUNCTUATION),
+
+          Symbol_Math = TO_MASK(UnicodeCE::U_MATH_SYMBOL),
+          Symbol_Currency = TO_MASK(UnicodeCE::U_CURRENCY_SYMBOL),
+          Symbol_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_SYMBOL),
+          Symbol_Other = TO_MASK(UnicodeCE::U_OTHER_SYMBOL),
+
+          Punctuation_InitialQuote = TO_MASK(UnicodeCE::U_INITIAL_PUNCTUATION),
+          Punctuation_FinalQuote = TO_MASK(UnicodeCE::U_FINAL_PUNCTUATION)
+        };
+
+        CharCategory category(unsigned int);
+
+        bool isSpace(wchar_t);
+        bool isLetter(wchar_t);
+        bool isPrintableChar(wchar_t);
+        bool isUpper(wchar_t);
+        bool isLower(wchar_t);
+        bool isPunct(wchar_t);
+        bool isDigit(wchar_t);
+        inline bool isSeparatorSpace(wchar_t c) { return category(c) == Separator_Space; }
+        inline bool isHighSurrogate(wchar_t c) { return (c & 0xfc00) == 0xd800; }
+        inline bool isLowSurrogate(wchar_t c) { return (c & 0xfc00) == 0xdc00; }
+
+        wchar_t toLower(wchar_t);
+        wchar_t toUpper(wchar_t);
+        wchar_t foldCase(wchar_t);
+        wchar_t toTitleCase(wchar_t);
+        int toLower(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError);
+        int toUpper(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError);
+        int foldCase(UChar* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError);
+
+        int digitValue(wchar_t);
+
+        wchar_t mirroredChar(UChar32);
+        unsigned char combiningClass(UChar32);
+        DecompositionType decompositionType(UChar32);
+        Direction direction(UChar32);
+        inline bool isArabicChar(UChar32)
+        {
+            return false; // FIXME: implement!
+        }
+
+        inline bool hasLineBreakingPropertyComplexContext(UChar32)
+        {
+            return false; // FIXME: implement!
+        }
+
+        inline int umemcasecmp(const wchar_t* a, const wchar_t* b, int len)
+        {
+            for (int i = 0; i < len; ++i) {
+                wchar_t c1 = foldCase(a[i]);
+                wchar_t c2 = foldCase(b[i]);
+                if (c1 != c2)
+                    return c1 - c2;
+            }
+            return 0;
+        }
+
+        inline UChar32 surrogateToUcs4(wchar_t high, wchar_t low)
+        {
+            return (UChar32(high) << 10) + low - 0x35fdc00;
+        }
+
+    }   // namespace Unicode
+
+}   // namespace WTF
+
+#endif
+// vim: ts=2 sw=2 et
index 9f1eaa68222e2b9e6a6bc299ea5fb74e1b22cc02..ee70b59b670aa1b4b3fe930161fc299f2acd7f97 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
 /*
  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,7 +32,7 @@
 
 #include "Assertions.h"
 #include "Threading.h"
 
 #include "Assertions.h"
 #include "Threading.h"
-#if !PLATFORM(WINCE)
+#if !OS(WINCE)
 #include <windows.h>
 #endif
 
 #include <windows.h>
 #endif
 
@@ -55,15 +56,26 @@ void initializeMainThreadPlatform()
     if (threadingWindowHandle)
         return;
 
     if (threadingWindowHandle)
         return;
 
+    HWND hWndParent = 0;
+#if OS(WINCE)
+    WNDCLASS wcex;
+    memset(&wcex, 0, sizeof(WNDCLASS));
+#else
     WNDCLASSEX wcex;
     memset(&wcex, 0, sizeof(WNDCLASSEX));
     wcex.cbSize = sizeof(WNDCLASSEX);
     WNDCLASSEX wcex;
     memset(&wcex, 0, sizeof(WNDCLASSEX));
     wcex.cbSize = sizeof(WNDCLASSEX);
+#endif
     wcex.lpfnWndProc    = ThreadingWindowWndProc;
     wcex.lpszClassName  = kThreadingWindowClassName;
     wcex.lpfnWndProc    = ThreadingWindowWndProc;
     wcex.lpszClassName  = kThreadingWindowClassName;
+#if OS(WINCE)
+    RegisterClass(&wcex);
+#else
     RegisterClassEx(&wcex);
     RegisterClassEx(&wcex);
+    hWndParent = HWND_MESSAGE;
+#endif
 
     threadingWindowHandle = CreateWindow(kThreadingWindowClassName, 0, 0,
 
     threadingWindowHandle = CreateWindow(kThreadingWindowClassName, 0, 0,
-       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, 0, 0);
+       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hWndParent, 0, 0, 0);
     threadingFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.MainThreadFired");
 }
 
     threadingFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.MainThreadFired");
 }
 
diff --git a/wtf/wince/FastMallocWince.h b/wtf/wince/FastMallocWince.h
new file mode 100644 (file)
index 0000000..37174f0
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007-2009 Torch Mobile, Inc. All rights reserved
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FastMallocWince_h
+#define FastMallocWince_h
+
+#include <new.h>
+
+#ifdef __cplusplus
+#include <new>
+#include "MemoryManager.h"
+extern "C" {
+#endif
+
+void* fastMalloc(size_t n);
+void* fastCalloc(size_t n_elements, size_t element_size);
+void fastFree(void* p);
+void* fastRealloc(void* p, size_t n);
+void* fastZeroedMalloc(size_t n);
+// These functions return 0 if an allocation fails.
+void* tryFastMalloc(size_t n);
+void* tryFastZeroedMalloc(size_t n);
+void* tryFastCalloc(size_t n_elements, size_t element_size);
+void* tryFastRealloc(void* p, size_t n);
+char* fastStrDup(const char*);
+
+#ifndef NDEBUG
+void fastMallocForbid();
+void fastMallocAllow();
+#endif
+
+#if !defined(USE_SYSTEM_MALLOC) || !USE_SYSTEM_MALLOC
+
+#define malloc(n)                           fastMalloc(n)
+#define calloc(n_elements, element_size)    fastCalloc(n_elements, element_size)
+#define realloc(p, n)                       fastRealloc(p, n)
+#define free(p)                             fastFree(p)
+#define strdup(p)                           fastStrDup(p)
+
+#else
+
+#define strdup(p)                           _strdup(p)
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+#if !defined(USE_SYSTEM_MALLOC) || !USE_SYSTEM_MALLOC
+static inline void* __cdecl operator new(size_t s) { return fastMalloc(s); }
+static inline void __cdecl operator delete(void* p) { fastFree(p); }
+static inline void* __cdecl operator new[](size_t s) { return fastMalloc(s); }
+static inline void __cdecl operator delete[](void* p) { fastFree(p); }
+static inline void* operator new(size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); }
+static inline void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); }
+static inline void* operator new[](size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); }
+static inline void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); }
+#endif
+
+namespace WTF {
+    // This defines a type which holds an unsigned integer and is the same
+    // size as the minimally aligned memory allocation.
+    typedef unsigned long long AllocAlignmentInteger;
+
+    namespace Internal {
+        enum AllocType {                    // Start with an unusual number instead of zero, because zero is common.
+            AllocTypeMalloc = 0x375d6750,   // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc.
+            AllocTypeClassNew,              // Encompasses class operator new from FastAllocBase.
+            AllocTypeClassNewArray,         // Encompasses class operator new[] from FastAllocBase.
+            AllocTypeFastNew,               // Encompasses fastNew.
+            AllocTypeFastNewArray,          // Encompasses fastNewArray.
+            AllocTypeNew,                   // Encompasses global operator new.
+            AllocTypeNewArray               // Encompasses global operator new[].
+        };
+    }
+
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+
+    // Malloc validation is a scheme whereby a tag is attached to an
+    // allocation which identifies how it was originally allocated.
+    // This allows us to verify that the freeing operation matches the
+    // allocation operation. If memory is allocated with operator new[]
+    // but freed with free or delete, this system would detect that.
+    // In the implementation here, the tag is an integer prepended to
+    // the allocation memory which is assigned one of the AllocType
+    // enumeration values. An alternative implementation of this
+    // scheme could store the tag somewhere else or ignore it.
+    // Users of FastMalloc don't need to know or care how this tagging
+    // is implemented.
+
+    namespace Internal {
+
+        // Return the AllocType tag associated with the allocated block p.
+        inline AllocType fastMallocMatchValidationType(const void* p)
+        {
+            const AllocAlignmentInteger* type = static_cast<const AllocAlignmentInteger*>(p) - 1;
+            return static_cast<AllocType>(*type);
+        }
+
+        // Return the address of the AllocType tag associated with the allocated block p.
+        inline AllocAlignmentInteger* fastMallocMatchValidationValue(void* p)
+        {
+            return reinterpret_cast<AllocAlignmentInteger*>(static_cast<char*>(p) - sizeof(AllocAlignmentInteger));
+        }
+
+        // Set the AllocType tag to be associaged with the allocated block p.
+        inline void setFastMallocMatchValidationType(void* p, AllocType allocType)
+        {
+            AllocAlignmentInteger* type = static_cast<AllocAlignmentInteger*>(p) - 1;
+            *type = static_cast<AllocAlignmentInteger>(allocType);
+        }
+
+        // Handle a detected alloc/free mismatch. By default this calls CRASH().
+        void fastMallocMatchFailed(void* p);
+
+    } // namespace Internal
+
+    // This is a higher level function which is used by FastMalloc-using code.
+    inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType)
+    {
+        if (!p)
+            return;
+
+        Internal::setFastMallocMatchValidationType(p, allocType);
+    }
+
+    // This is a higher level function which is used by FastMalloc-using code.
+    inline void fastMallocMatchValidateFree(void* p, Internal::AllocType allocType)
+    {
+        if (!p)
+            return;
+
+        if (Internal::fastMallocMatchValidationType(p) != allocType)
+            Internal::fastMallocMatchFailed(p);
+        Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc);  // Set it to this so that fastFree thinks it's OK.
+    }
+
+#else
+
+    inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType)
+    {
+    }
+
+    inline void fastMallocMatchValidateFree(void*, Internal::AllocType)
+    {
+    }
+
+#endif
+
+} // namespace WTF
+
+#endif
+
+#endif // FastMallocWince_h
+
diff --git a/wtf/wince/MemoryManager.cpp b/wtf/wince/MemoryManager.cpp
new file mode 100644 (file)
index 0000000..81d4f80
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2008-2009 Torch Mobile Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "MemoryManager.h"
+
+#undef malloc
+#undef calloc
+#undef realloc
+#undef free
+#undef strdup
+#undef _strdup
+#undef VirtualAlloc
+#undef VirtualFree
+
+#include <malloc.h>
+#include <windows.h>
+
+namespace WTF {
+
+MemoryManager* memoryManager()
+{
+    static MemoryManager mm;
+    return &mm;
+}
+
+MemoryManager::MemoryManager()
+: m_allocationCanFail(false)
+{
+}
+
+MemoryManager::~MemoryManager()
+{
+}
+
+HBITMAP MemoryManager::createCompatibleBitmap(HDC hdc, int width, int height)
+{
+    return ::CreateCompatibleBitmap(hdc, width, height);
+}
+
+HBITMAP MemoryManager::createDIBSection(const BITMAPINFO* pbmi, void** ppvBits)
+{
+    return ::CreateDIBSection(0, pbmi, DIB_RGB_COLORS, ppvBits, 0, 0);
+}
+
+void* MemoryManager::m_malloc(size_t size)
+{
+    return malloc(size);
+}
+
+void* MemoryManager::m_calloc(size_t num, size_t size)
+{
+    return calloc(num, size);
+}
+
+void* MemoryManager::m_realloc(void* p, size_t size)
+{
+    return realloc(p, size);
+}
+
+void MemoryManager::m_free(void* p)
+{
+    return free(p);
+}
+
+bool MemoryManager::resizeMemory(void*, size_t)
+{
+    return false;
+}
+
+void* MemoryManager::allocate64kBlock()
+{
+    return VirtualAlloc(0, 65536, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+}
+
+void MemoryManager::free64kBlock(void* p)
+{
+    VirtualFree(p, 65536, MEM_RELEASE);
+}
+
+bool MemoryManager::onIdle(DWORD& timeLimitMs)
+{
+    return false;
+}
+
+LPVOID MemoryManager::virtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect)
+{
+    return ::VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
+}
+
+BOOL MemoryManager::virtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType)
+{
+    return ::VirtualFree(lpAddress, dwSize, dwFreeType);
+}
+
+
+#if defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC
+
+void *fastMalloc(size_t n) { return malloc(n); }
+void *fastCalloc(size_t n_elements, size_t element_size) { return calloc(n_elements, element_size); }
+void fastFree(void* p) { return free(p); }
+void *fastRealloc(void* p, size_t n) { return realloc(p, n); }
+
+#else
+
+void *fastMalloc(size_t n) { return MemoryManager::m_malloc(n); }
+void *fastCalloc(size_t n_elements, size_t element_size) { return MemoryManager::m_calloc(n_elements, element_size); }
+void fastFree(void* p) { return MemoryManager::m_free(p); }
+void *fastRealloc(void* p, size_t n) { return MemoryManager::m_realloc(p, n); }
+
+#endif
+
+#ifndef NDEBUG
+void fastMallocForbid() {}
+void fastMallocAllow() {}
+#endif
+
+void* fastZeroedMalloc(size_t n)
+{
+    void* p = fastMalloc(n);
+    if (p)
+        memset(p, 0, n);
+    return p;
+}
+
+TryMallocReturnValue tryFastMalloc(size_t n)
+{
+    MemoryAllocationCanFail canFail;
+    return fastMalloc(n);
+}
+
+TryMallocReturnValue tryFastZeroedMalloc(size_t n)
+{
+    MemoryAllocationCanFail canFail;
+    return fastZeroedMalloc(n);
+}
+
+TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size)
+{
+    MemoryAllocationCanFail canFail;
+    return fastCalloc(n_elements, element_size);
+}
+
+TryMallocReturnValue tryFastRealloc(void* p, size_t n)
+{
+    MemoryAllocationCanFail canFail;
+    return fastRealloc(p, n);
+}
+
+char* fastStrDup(const char* str)
+{
+    return _strdup(str);
+}
+
+}
\ No newline at end of file
diff --git a/wtf/wince/MemoryManager.h b/wtf/wince/MemoryManager.h
new file mode 100644 (file)
index 0000000..f405612
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008-2009 Torch Mobile Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include <winbase.h>
+
+typedef struct HBITMAP__* HBITMAP;
+typedef struct HDC__* HDC;
+typedef void *HANDLE;
+typedef struct tagBITMAPINFO BITMAPINFO;
+
+namespace WTF {
+
+    class MemoryManager {
+    public:
+        MemoryManager();
+        ~MemoryManager();
+
+        bool allocationCanFail() const { return m_allocationCanFail; }
+        void setAllocationCanFail(bool c) { m_allocationCanFail = c; }
+
+        static HBITMAP createCompatibleBitmap(HDC hdc, int width, int height);
+        static HBITMAP createDIBSection(const BITMAPINFO* pbmi, void** ppvBits);
+        static void* m_malloc(size_t size);
+        static void* m_calloc(size_t num, size_t size);
+        static void* m_realloc(void* p, size_t size);
+        static void m_free(void*);
+        static bool resizeMemory(void* p, size_t newSize);
+        static void* allocate64kBlock();
+        static void free64kBlock(void*);
+        static bool onIdle(DWORD& timeLimitMs);
+        static LPVOID virtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect);
+        static BOOL virtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType);
+
+    private:
+        friend MemoryManager* memoryManager();
+
+        bool m_allocationCanFail;
+    };
+
+    MemoryManager* memoryManager();
+
+    class MemoryAllocationCanFail {
+    public:
+        MemoryAllocationCanFail() : m_old(memoryManager()->allocationCanFail()) { memoryManager()->setAllocationCanFail(true); }
+        ~MemoryAllocationCanFail() { memoryManager()->setAllocationCanFail(m_old); }
+    private:
+        bool m_old;
+    };
+
+    class MemoryAllocationCannotFail {
+    public:
+        MemoryAllocationCannotFail() : m_old(memoryManager()->allocationCanFail()) { memoryManager()->setAllocationCanFail(false); }
+        ~MemoryAllocationCannotFail() { memoryManager()->setAllocationCanFail(m_old); }
+    private:
+        bool m_old;
+    };
+}
+
+using WTF::MemoryManager;
+using WTF::memoryManager;
+using WTF::MemoryAllocationCanFail;
+using WTF::MemoryAllocationCannotFail;
diff --git a/wtf/wince/mt19937ar.c b/wtf/wince/mt19937ar.c
new file mode 100644 (file)
index 0000000..4715958
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+   A C-program for MT19937, with initialization improved 2002/1/26.
+   Coded by Takuji Nishimura and Makoto Matsumoto.
+
+   Before using, initialize the state by using init_genrand(seed)
+   or init_by_array(init_key, key_length).
+
+   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+     1. Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+
+     2. Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+     3. The names of its contributors may not be used to endorse or promote
+        products derived from this software without specific prior written
+        permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+   Any feedback is very welcome.
+   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+*/
+
+#include <stdio.h>
+
+/* Period parameters */
+#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
+#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
+
+static unsigned long mt[N]; /* the array for the state vector  */
+static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
+
+/* initializes mt[N] with a seed */
+void init_genrand(unsigned long s)
+{
+    mt[0]= s & 0xffffffffUL;
+    for (mti=1; mti<N; mti++) {
+        mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
+        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
+        /* In the previous versions, MSBs of the seed affect   */
+        /* only MSBs of the array mt[].                        */
+        /* 2002/01/09 modified by Makoto Matsumoto             */
+        mt[mti] &= 0xffffffffUL;
+        /* for >32 bit machines */
+    }
+}
+
+/* initialize by an array with array-length */
+/* init_key is the array for initializing keys */
+/* key_length is its length */
+/* slight change for C++, 2004/2/26 */
+void init_by_array(unsigned long init_key[],int key_length)
+{
+    int i, j, k;
+    init_genrand(19650218UL);
+    i=1; j=0;
+    k = (N>key_length ? N : key_length);
+    for (; k; k--) {
+        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+          + init_key[j] + j; /* non linear */
+        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        i++; j++;
+        if (i>=N) { mt[0] = mt[N-1]; i=1; }
+        if (j>=key_length) j=0;
+    }
+    for (k=N-1; k; k--) {
+        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
+          - i; /* non linear */
+        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        i++;
+        if (i>=N) { mt[0] = mt[N-1]; i=1; }
+    }
+
+    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
+}
+
+/* generates a random number on [0,0xffffffff]-interval */
+unsigned long genrand_int32(void)
+{
+    unsigned long y;
+    static unsigned long mag01[2]={0x0UL, MATRIX_A};
+    /* mag01[x] = x * MATRIX_A  for x=0,1 */
+
+    if (mti >= N) { /* generate N words at one time */
+        int kk;
+
+        if (mti == N+1)   /* if init_genrand() has not been called, */
+            init_genrand(5489UL); /* a default initial seed is used */
+
+        for (kk=0;kk<N-M;kk++) {
+            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+        }
+        for (;kk<N-1;kk++) {
+            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+            mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+        }
+        y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+        mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+
+        mti = 0;
+    }
+
+    y = mt[mti++];
+
+    /* Tempering */
+    y ^= (y >> 11);
+    y ^= (y << 7) & 0x9d2c5680UL;
+    y ^= (y << 15) & 0xefc60000UL;
+    y ^= (y >> 18);
+
+    return y;
+}
+
+/* generates a random number on [0,0x7fffffff]-interval */
+long genrand_int31(void)
+{
+    return (long)(genrand_int32()>>1);
+}
+
+/* generates a random number on [0,1]-real-interval */
+double genrand_real1(void)
+{
+    return genrand_int32()*(1.0/4294967295.0);
+    /* divided by 2^32-1 */
+}
+
+/* generates a random number on [0,1)-real-interval */
+double genrand_real2(void)
+{
+    return genrand_int32()*(1.0/4294967296.0);
+    /* divided by 2^32 */
+}
+
+/* generates a random number on (0,1)-real-interval */
+double genrand_real3(void)
+{
+    return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
+    /* divided by 2^32 */
+}
+
+/* generates a random number on [0,1) with 53-bit resolution*/
+double genrand_res53(void)
+{
+    unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
+    return(a*67108864.0+b)*(1.0/9007199254740992.0);
+}
index c7b3c8119f335eeafabc74644d936172b07bec72..9cd3d123c1cf8b6294a4bd0859aa388a149eaff3 100644 (file)
@@ -708,7 +708,7 @@ const char* compileRegex(const UString& patternString, RegexPattern& pattern)
         unsigned numSubpatterns = pattern.m_numSubpatterns;
 
         constructor.reset();
         unsigned numSubpatterns = pattern.m_numSubpatterns;
 
         constructor.reset();
-#ifndef NDEBUG
+#if !ASSERT_DISABLED
         const char* error =
 #endif
             parse(constructor, patternString, numSubpatterns);
         const char* error =
 #endif
             parse(constructor, patternString, numSubpatterns);
index b0aae650280ac224d81ee41525d5fa5207503348..d0880866a35653b20fab2bf881acbef8385c1c99 100644 (file)
@@ -20,7 +20,7 @@
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "config.h"
  */
 
 #include "config.h"
@@ -90,7 +90,7 @@ public:
             : term(0)
         {
         }
             : term(0)
         {
         }
-        
+
         void* operator new(size_t, void* where)
         {
             return where;
         void* operator new(size_t, void* where)
         {
             return where;
@@ -124,7 +124,7 @@ public:
                 subpatternBackup[i] = output[(firstSubpatternId << 1) + i];
                 output[(firstSubpatternId << 1) + i] = -1;
             }
                 subpatternBackup[i] = output[(firstSubpatternId << 1) + i];
                 output[(firstSubpatternId << 1) + i] = -1;
             }
-            
+
             new(getDisjunctionContext(term)) DisjunctionContext();
         }
 
             new(getDisjunctionContext(term)) DisjunctionContext();
         }
 
@@ -138,7 +138,7 @@ public:
             for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i)
                 output[(firstSubpatternId << 1) + i] = subpatternBackup[i];
         }
             for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i)
                 output[(firstSubpatternId << 1) + i] = subpatternBackup[i];
         }
-        
+
         DisjunctionContext* getDisjunctionContext(ByteTerm& term)
         {
             return reinterpret_cast<DisjunctionContext*>(&(subpatternBackup[term.atom.parenthesesDisjunction->m_numSubpatterns << 1]));
         DisjunctionContext* getDisjunctionContext(ByteTerm& term)
         {
             return reinterpret_cast<DisjunctionContext*>(&(subpatternBackup[term.atom.parenthesesDisjunction->m_numSubpatterns << 1]));
@@ -208,7 +208,7 @@ public:
                 return input[pos - 1];
             return -1;
         }
                 return input[pos - 1];
             return -1;
         }
-        
+
         unsigned getPos()
         {
             return pos;
         unsigned getPos()
         {
             return pos;
@@ -218,7 +218,7 @@ public:
         {
             pos = p;
         }
         {
             pos = p;
         }
-        
+
         bool atStart()
         {
             return pos == 0;
         bool atStart()
         {
             return pos == 0;
@@ -284,7 +284,7 @@ public:
     {
         if (input.atEnd())
             return false;
     {
         if (input.atEnd())
             return false;
-        
+
         int ch = input.read();
 
         if (pattern->m_ignoreCase ? ((Unicode::toLower(testChar) == ch) || (Unicode::toUpper(testChar) == ch)) : (testChar == ch)) {
         int ch = input.read();
 
         if (pattern->m_ignoreCase ? ((Unicode::toLower(testChar) == ch) || (Unicode::toUpper(testChar) == ch)) : (testChar == ch)) {
@@ -341,7 +341,7 @@ public:
                 return false;
             }
         }
                 return false;
             }
         }
-        
+
         return true;
     }
 
         return true;
     }
 
@@ -606,10 +606,10 @@ public:
 
             if (matchDisjunction(term.atom.parenthesesDisjunction, context->getDisjunctionContext(term), true))
                 return true;
 
             if (matchDisjunction(term.atom.parenthesesDisjunction, context->getDisjunctionContext(term), true))
                 return true;
-            
+
             resetMatches(term, context);
             resetMatches(term, context);
-            freeParenthesesDisjunctionContext(context);
             popParenthesesDisjunctionContext(backTrack);
             popParenthesesDisjunctionContext(backTrack);
+            freeParenthesesDisjunctionContext(context);
         }
 
         return false;
         }
 
         return false;
@@ -910,8 +910,8 @@ public:
                 }
             } else {
                 resetMatches(term, context);
                 }
             } else {
                 resetMatches(term, context);
-                freeParenthesesDisjunctionContext(context);
                 popParenthesesDisjunctionContext(backTrack);
                 popParenthesesDisjunctionContext(backTrack);
+                freeParenthesesDisjunctionContext(context);
             }
 
             if (backTrack->matchAmount) {
             }
 
             if (backTrack->matchAmount) {
@@ -946,11 +946,11 @@ public:
                     }
                     return true;
                 }
                     }
                     return true;
                 }
-                
+
                 // pop a match off the stack
                 resetMatches(term, context);
                 // pop a match off the stack
                 resetMatches(term, context);
-                freeParenthesesDisjunctionContext(context);
                 popParenthesesDisjunctionContext(backTrack);
                 popParenthesesDisjunctionContext(backTrack);
+                freeParenthesesDisjunctionContext(context);
             }
 
             return false;
             }
 
             return false;
@@ -1266,37 +1266,37 @@ public:
     ByteCompiler(RegexPattern& pattern)
         : m_pattern(pattern)
     {
     ByteCompiler(RegexPattern& pattern)
         : m_pattern(pattern)
     {
-        bodyDisjunction = 0;
-        currentAlternativeIndex = 0;
+        m_bodyDisjunction = 0;
+        m_currentAlternativeIndex = 0;
     }
     }
-    
+
     BytecodePattern* compile()
     {
         regexBegin(m_pattern.m_numSubpatterns, m_pattern.m_body->m_callFrameSize);
         emitDisjunction(m_pattern.m_body);
         regexEnd();
 
     BytecodePattern* compile()
     {
         regexBegin(m_pattern.m_numSubpatterns, m_pattern.m_body->m_callFrameSize);
         emitDisjunction(m_pattern.m_body);
         regexEnd();
 
-        return new BytecodePattern(bodyDisjunction, m_allParenthesesInfo, m_pattern);
+        return new BytecodePattern(m_bodyDisjunction, m_allParenthesesInfo, m_pattern);
     }
     }
-    
+
     void checkInput(unsigned count)
     {
     void checkInput(unsigned count)
     {
-        bodyDisjunction->terms.append(ByteTerm::CheckInput(count));
+        m_bodyDisjunction->terms.append(ByteTerm::CheckInput(count));
     }
 
     void assertionBOL(int inputPosition)
     {
     }
 
     void assertionBOL(int inputPosition)
     {
-        bodyDisjunction->terms.append(ByteTerm::BOL(inputPosition));
+        m_bodyDisjunction->terms.append(ByteTerm::BOL(inputPosition));
     }
 
     void assertionEOL(int inputPosition)
     {
     }
 
     void assertionEOL(int inputPosition)
     {
-        bodyDisjunction->terms.append(ByteTerm::EOL(inputPosition));
+        m_bodyDisjunction->terms.append(ByteTerm::EOL(inputPosition));
     }
 
     void assertionWordBoundary(bool invert, int inputPosition)
     {
     }
 
     void assertionWordBoundary(bool invert, int inputPosition)
     {
-        bodyDisjunction->terms.append(ByteTerm::WordBoundary(invert, inputPosition));
+        m_bodyDisjunction->terms.append(ByteTerm::WordBoundary(invert, inputPosition));
     }
 
     void atomPatternCharacter(UChar ch, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
     }
 
     void atomPatternCharacter(UChar ch, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
@@ -1304,60 +1304,60 @@ public:
         if (m_pattern.m_ignoreCase) {
             UChar lo = Unicode::toLower(ch);
             UChar hi = Unicode::toUpper(ch);
         if (m_pattern.m_ignoreCase) {
             UChar lo = Unicode::toLower(ch);
             UChar hi = Unicode::toUpper(ch);
-            
+
             if (lo != hi) {
             if (lo != hi) {
-                bodyDisjunction->terms.append(ByteTerm(lo, hi, inputPosition, frameLocation, quantityCount, quantityType));
+                m_bodyDisjunction->terms.append(ByteTerm(lo, hi, inputPosition, frameLocation, quantityCount, quantityType));
                 return;
             }
         }
 
                 return;
             }
         }
 
-        bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantityCount, quantityType));
+        m_bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantityCount, quantityType));
     }
     }
-    
+
     void atomCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
     {
     void atomCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
     {
-        bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition));
+        m_bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition));
 
 
-        bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount;
-        bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
-        bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
     }
 
     void atomBackReference(unsigned subpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
     {
         ASSERT(subpatternId);
 
     }
 
     void atomBackReference(unsigned subpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
     {
         ASSERT(subpatternId);
 
-        bodyDisjunction->terms.append(ByteTerm::BackReference(subpatternId, inputPosition));
+        m_bodyDisjunction->terms.append(ByteTerm::BackReference(subpatternId, inputPosition));
 
 
-        bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount;
-        bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
-        bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
     }
 
     void atomParenthesesSubpatternBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
     {
     }
 
     void atomParenthesesSubpatternBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
     {
-        int beginTerm = bodyDisjunction->terms.size();
+        int beginTerm = m_bodyDisjunction->terms.size();
 
 
-        bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, inputPosition));
-        bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
-        bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
-        bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, inputPosition));
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
 
 
-        m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, currentAlternativeIndex));
-        currentAlternativeIndex = beginTerm + 1;
+        m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
+        m_currentAlternativeIndex = beginTerm + 1;
     }
 
     void atomParentheticalAssertionBegin(unsigned subpatternId, bool invert, unsigned frameLocation, unsigned alternativeFrameLocation)
     {
     }
 
     void atomParentheticalAssertionBegin(unsigned subpatternId, bool invert, unsigned frameLocation, unsigned alternativeFrameLocation)
     {
-        int beginTerm = bodyDisjunction->terms.size();
+        int beginTerm = m_bodyDisjunction->terms.size();
 
 
-        bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionBegin, subpatternId, invert, 0));
-        bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
-        bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
-        bodyDisjunction->terms[bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionBegin, subpatternId, invert, 0));
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
 
 
-        m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, currentAlternativeIndex));
-        currentAlternativeIndex = beginTerm + 1;
+        m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
+        m_currentAlternativeIndex = beginTerm + 1;
     }
 
     unsigned popParenthesesStack()
     }
 
     unsigned popParenthesesStack()
@@ -1365,12 +1365,12 @@ public:
         ASSERT(m_parenthesesStack.size());
         int stackEnd = m_parenthesesStack.size() - 1;
         unsigned beginTerm = m_parenthesesStack[stackEnd].beginTerm;
         ASSERT(m_parenthesesStack.size());
         int stackEnd = m_parenthesesStack.size() - 1;
         unsigned beginTerm = m_parenthesesStack[stackEnd].beginTerm;
-        currentAlternativeIndex = m_parenthesesStack[stackEnd].savedAlternativeIndex;
+        m_currentAlternativeIndex = m_parenthesesStack[stackEnd].savedAlternativeIndex;
         m_parenthesesStack.shrink(stackEnd);
 
         m_parenthesesStack.shrink(stackEnd);
 
-        ASSERT(beginTerm < bodyDisjunction->terms.size());
-        ASSERT(currentAlternativeIndex < bodyDisjunction->terms.size());
-        
+        ASSERT(beginTerm < m_bodyDisjunction->terms.size());
+        ASSERT(m_currentAlternativeIndex < m_bodyDisjunction->terms.size());
+
         return beginTerm;
     }
 
         return beginTerm;
     }
 
@@ -1387,25 +1387,25 @@ public:
     void closeAlternative(int beginTerm)
     {
         int origBeginTerm = beginTerm;
     void closeAlternative(int beginTerm)
     {
         int origBeginTerm = beginTerm;
-        ASSERT(bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeBegin);
-        int endIndex = bodyDisjunction->terms.size();
+        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeBegin);
+        int endIndex = m_bodyDisjunction->terms.size();
 
 
-        unsigned frameLocation = bodyDisjunction->terms[beginTerm].frameLocation;
+        unsigned frameLocation = m_bodyDisjunction->terms[beginTerm].frameLocation;
 
 
-        if (!bodyDisjunction->terms[beginTerm].alternative.next)
-            bodyDisjunction->terms.remove(beginTerm);
+        if (!m_bodyDisjunction->terms[beginTerm].alternative.next)
+            m_bodyDisjunction->terms.remove(beginTerm);
         else {
         else {
-            while (bodyDisjunction->terms[beginTerm].alternative.next) {
-                beginTerm += bodyDisjunction->terms[beginTerm].alternative.next;
-                ASSERT(bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeDisjunction);
-                bodyDisjunction->terms[beginTerm].alternative.end = endIndex - beginTerm;
-                bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
+            while (m_bodyDisjunction->terms[beginTerm].alternative.next) {
+                beginTerm += m_bodyDisjunction->terms[beginTerm].alternative.next;
+                ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeDisjunction);
+                m_bodyDisjunction->terms[beginTerm].alternative.end = endIndex - beginTerm;
+                m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
             }
             }
-            
-            bodyDisjunction->terms[beginTerm].alternative.next = origBeginTerm - beginTerm;
 
 
-            bodyDisjunction->terms.append(ByteTerm::AlternativeEnd());
-            bodyDisjunction->terms[endIndex].frameLocation = frameLocation;
+            m_bodyDisjunction->terms[beginTerm].alternative.next = origBeginTerm - beginTerm;
+
+            m_bodyDisjunction->terms.append(ByteTerm::AlternativeEnd());
+            m_bodyDisjunction->terms[endIndex].frameLocation = frameLocation;
         }
     }
 
         }
     }
 
@@ -1413,46 +1413,46 @@ public:
     {
         int beginTerm = 0;
         int origBeginTerm = 0;
     {
         int beginTerm = 0;
         int origBeginTerm = 0;
-        ASSERT(bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeBegin);
-        int endIndex = bodyDisjunction->terms.size();
+        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeBegin);
+        int endIndex = m_bodyDisjunction->terms.size();
 
 
-        unsigned frameLocation = bodyDisjunction->terms[beginTerm].frameLocation;
+        unsigned frameLocation = m_bodyDisjunction->terms[beginTerm].frameLocation;
 
 
-        while (bodyDisjunction->terms[beginTerm].alternative.next) {
-            beginTerm += bodyDisjunction->terms[beginTerm].alternative.next;
-            ASSERT(bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeDisjunction);
-            bodyDisjunction->terms[beginTerm].alternative.end = endIndex - beginTerm;
-            bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
+        while (m_bodyDisjunction->terms[beginTerm].alternative.next) {
+            beginTerm += m_bodyDisjunction->terms[beginTerm].alternative.next;
+            ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeDisjunction);
+            m_bodyDisjunction->terms[beginTerm].alternative.end = endIndex - beginTerm;
+            m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
         }
         }
-        
-        bodyDisjunction->terms[beginTerm].alternative.next = origBeginTerm - beginTerm;
 
 
-        bodyDisjunction->terms.append(ByteTerm::BodyAlternativeEnd());
-        bodyDisjunction->terms[endIndex].frameLocation = frameLocation;
+        m_bodyDisjunction->terms[beginTerm].alternative.next = origBeginTerm - beginTerm;
+
+        m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeEnd());
+        m_bodyDisjunction->terms[endIndex].frameLocation = frameLocation;
     }
 
     void atomParenthesesEnd(bool doInline, unsigned lastSubpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType, unsigned callFrameSize = 0)
     {
         unsigned beginTerm = popParenthesesStack();
         closeAlternative(beginTerm + 1);
     }
 
     void atomParenthesesEnd(bool doInline, unsigned lastSubpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType, unsigned callFrameSize = 0)
     {
         unsigned beginTerm = popParenthesesStack();
         closeAlternative(beginTerm + 1);
-        unsigned endTerm = bodyDisjunction->terms.size();
+        unsigned endTerm = m_bodyDisjunction->terms.size();
 
 
-        bool isAssertion = bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParentheticalAssertionBegin;
-        bool invertOrCapture = bodyDisjunction->terms[beginTerm].invertOrCapture;
-        unsigned subpatternId = bodyDisjunction->terms[beginTerm].atom.subpatternId;
+        bool isAssertion = m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParentheticalAssertionBegin;
+        bool invertOrCapture = m_bodyDisjunction->terms[beginTerm].invertOrCapture;
+        unsigned subpatternId = m_bodyDisjunction->terms[beginTerm].atom.subpatternId;
 
 
-        bodyDisjunction->terms.append(ByteTerm(isAssertion ? ByteTerm::TypeParentheticalAssertionEnd : ByteTerm::TypeParenthesesSubpatternOnceEnd, subpatternId, invertOrCapture, inputPosition));
-        bodyDisjunction->terms[beginTerm].atom.parenthesesWidth = endTerm - beginTerm;
-        bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm;
-        bodyDisjunction->terms[endTerm].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.append(ByteTerm(isAssertion ? ByteTerm::TypeParentheticalAssertionEnd : ByteTerm::TypeParenthesesSubpatternOnceEnd, subpatternId, invertOrCapture, inputPosition));
+        m_bodyDisjunction->terms[beginTerm].atom.parenthesesWidth = endTerm - beginTerm;
+        m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm;
+        m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation;
 
         if (doInline) {
 
         if (doInline) {
-            bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
-            bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
-            bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount;
-            bodyDisjunction->terms[endTerm].atom.quantityType = quantityType;
+            m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
+            m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
+            m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount;
+            m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType;
         } else {
         } else {
-            ByteTerm& parenthesesBegin = bodyDisjunction->terms[beginTerm];
+            ByteTerm& parenthesesBegin = m_bodyDisjunction->terms[beginTerm];
             ASSERT(parenthesesBegin.type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
 
             bool invertOrCapture = parenthesesBegin.invertOrCapture;
             ASSERT(parenthesesBegin.type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
 
             bool invertOrCapture = parenthesesBegin.invertOrCapture;
@@ -1463,26 +1463,26 @@ public:
 
             parenthesesDisjunction->terms.append(ByteTerm::SubpatternBegin());
             for (unsigned termInParentheses = beginTerm + 1; termInParentheses < endTerm; ++termInParentheses)
 
             parenthesesDisjunction->terms.append(ByteTerm::SubpatternBegin());
             for (unsigned termInParentheses = beginTerm + 1; termInParentheses < endTerm; ++termInParentheses)
-                parenthesesDisjunction->terms.append(bodyDisjunction->terms[termInParentheses]);
+                parenthesesDisjunction->terms.append(m_bodyDisjunction->terms[termInParentheses]);
             parenthesesDisjunction->terms.append(ByteTerm::SubpatternEnd());
 
             parenthesesDisjunction->terms.append(ByteTerm::SubpatternEnd());
 
-            bodyDisjunction->terms.shrink(beginTerm);
+            m_bodyDisjunction->terms.shrink(beginTerm);
 
             m_allParenthesesInfo.append(parenthesesDisjunction);
 
             m_allParenthesesInfo.append(parenthesesDisjunction);
-            bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, invertOrCapture, inputPosition));
+            m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, invertOrCapture, inputPosition));
 
 
-            bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
-            bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
-            bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
+            m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
+            m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
+            m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
         }
     }
 
     void regexBegin(unsigned numSubpatterns, unsigned callFrameSize)
     {
         }
     }
 
     void regexBegin(unsigned numSubpatterns, unsigned callFrameSize)
     {
-        bodyDisjunction = new ByteDisjunction(numSubpatterns, callFrameSize);
-        bodyDisjunction->terms.append(ByteTerm::BodyAlternativeBegin());
-        bodyDisjunction->terms[0].frameLocation = 0;
-        currentAlternativeIndex = 0;
+        m_bodyDisjunction = new ByteDisjunction(numSubpatterns, callFrameSize);
+        m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeBegin());
+        m_bodyDisjunction->terms[0].frameLocation = 0;
+        m_currentAlternativeIndex = 0;
     }
 
     void regexEnd()
     }
 
     void regexEnd()
@@ -1490,34 +1490,34 @@ public:
         closeBodyAlternative();
     }
 
         closeBodyAlternative();
     }
 
-    void alterantiveBodyDisjunction()
+    void alternativeBodyDisjunction()
     {
     {
-        int newAlternativeIndex = bodyDisjunction->terms.size();
-        bodyDisjunction->terms[currentAlternativeIndex].alternative.next = newAlternativeIndex - currentAlternativeIndex;
-        bodyDisjunction->terms.append(ByteTerm::BodyAlternativeDisjunction());
+        int newAlternativeIndex = m_bodyDisjunction->terms.size();
+        m_bodyDisjunction->terms[m_currentAlternativeIndex].alternative.next = newAlternativeIndex - m_currentAlternativeIndex;
+        m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeDisjunction());
 
 
-        currentAlternativeIndex = newAlternativeIndex;
+        m_currentAlternativeIndex = newAlternativeIndex;
     }
 
     }
 
-    void alterantiveDisjunction()
+    void alternativeDisjunction()
     {
     {
-        int newAlternativeIndex = bodyDisjunction->terms.size();
-        bodyDisjunction->terms[currentAlternativeIndex].alternative.next = newAlternativeIndex - currentAlternativeIndex;
-        bodyDisjunction->terms.append(ByteTerm::AlternativeDisjunction());
+        int newAlternativeIndex = m_bodyDisjunction->terms.size();
+        m_bodyDisjunction->terms[m_currentAlternativeIndex].alternative.next = newAlternativeIndex - m_currentAlternativeIndex;
+        m_bodyDisjunction->terms.append(ByteTerm::AlternativeDisjunction());
 
 
-        currentAlternativeIndex = newAlternativeIndex;
+        m_currentAlternativeIndex = newAlternativeIndex;
     }
 
     void emitDisjunction(PatternDisjunction* disjunction, unsigned inputCountAlreadyChecked = 0, unsigned parenthesesInputCountAlreadyChecked = 0)
     {
         for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
             unsigned currentCountAlreadyChecked = inputCountAlreadyChecked;
     }
 
     void emitDisjunction(PatternDisjunction* disjunction, unsigned inputCountAlreadyChecked = 0, unsigned parenthesesInputCountAlreadyChecked = 0)
     {
         for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
             unsigned currentCountAlreadyChecked = inputCountAlreadyChecked;
-        
+
             if (alt) {
                 if (disjunction == m_pattern.m_body)
             if (alt) {
                 if (disjunction == m_pattern.m_body)
-                    alterantiveBodyDisjunction();
+                    alternativeBodyDisjunction();
                 else
                 else
-                    alterantiveDisjunction();
+                    alternativeDisjunction();
             }
 
             PatternAlternative* alternative = disjunction->m_alternatives[alt];
             }
 
             PatternAlternative* alternative = disjunction->m_alternatives[alt];
@@ -1586,7 +1586,7 @@ public:
 
                 case PatternTerm::TypeParentheticalAssertion: {
                     unsigned alternativeFrameLocation = term.inputPosition + RegexStackSpaceForBackTrackInfoParentheticalAssertion;
 
                 case PatternTerm::TypeParentheticalAssertion: {
                     unsigned alternativeFrameLocation = term.inputPosition + RegexStackSpaceForBackTrackInfoParentheticalAssertion;
-                    
+
                     atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invertOrCapture, term.frameLocation, alternativeFrameLocation);
                     emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
                     atomParenthesesEnd(true, term.parentheses.lastSubpatternId, 0, term.frameLocation, term.quantityCount, term.quantityType);
                     atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invertOrCapture, term.frameLocation, alternativeFrameLocation);
                     emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
                     atomParenthesesEnd(true, term.parentheses.lastSubpatternId, 0, term.frameLocation, term.quantityCount, term.quantityType);
@@ -1599,8 +1599,8 @@ public:
 
 private:
     RegexPattern& m_pattern;
 
 private:
     RegexPattern& m_pattern;
-    ByteDisjunction* bodyDisjunction;
-    unsigned currentAlternativeIndex;
+    ByteDisjunction* m_bodyDisjunction;
+    unsigned m_currentAlternativeIndex;
     Vector<ParenthesesStackEntry> m_parenthesesStack;
     Vector<ByteDisjunction*> m_allParenthesesInfo;
 };
     Vector<ParenthesesStackEntry> m_parenthesesStack;
     Vector<ByteDisjunction*> m_allParenthesesInfo;
 };
index a8c122ac71572745a7e96173ce47fd15bcae566f..48c9a5ef855c4006458e40ac5950ece79097eece 100644 (file)
@@ -280,7 +280,7 @@ struct ByteTerm {
     }
 };
 
     }
 };
 
-class ByteDisjunction {
+class ByteDisjunction : public FastAllocBase {
 public:
     ByteDisjunction(unsigned numSubpatterns, unsigned frameSize)
         : m_numSubpatterns(numSubpatterns)
 public:
     ByteDisjunction(unsigned numSubpatterns, unsigned frameSize)
         : m_numSubpatterns(numSubpatterns)
@@ -293,7 +293,7 @@ public:
     unsigned m_frameSize;
 };
 
     unsigned m_frameSize;
 };
 
-struct BytecodePattern {
+struct BytecodePattern : FastAllocBase {
     BytecodePattern(ByteDisjunction* body, Vector<ByteDisjunction*> allParenthesesInfo, RegexPattern& pattern)
         : m_body(body)
         , m_ignoreCase(pattern.m_ignoreCase)
     BytecodePattern(ByteDisjunction* body, Vector<ByteDisjunction*> allParenthesesInfo, RegexPattern& pattern)
         : m_body(body)
         , m_ignoreCase(pattern.m_ignoreCase)
index 8e3640ac0d780c35c82d7223a81e12c4504f7db0..fcb8d86ae93f92c78b5347ad7631a888b6e4a672 100644 (file)
@@ -44,38 +44,36 @@ namespace JSC { namespace Yarr {
 class RegexGenerator : private MacroAssembler {
     friend void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline);
 
 class RegexGenerator : private MacroAssembler {
     friend void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline);
 
-#if PLATFORM_ARM_ARCH(7)
-    static const RegisterID input = ARM::r0;
-    static const RegisterID index = ARM::r1;
-    static const RegisterID length = ARM::r2;
-
-    static const RegisterID output = ARM::r4;
-    static const RegisterID regT0 = ARM::r5;
-    static const RegisterID regT1 = ARM::r6;
-
-    static const RegisterID returnRegister = ARM::r0;
-#endif
-#if PLATFORM(X86)
-    static const RegisterID input = X86::eax;
-    static const RegisterID index = X86::edx;
-    static const RegisterID length = X86::ecx;
-    static const RegisterID output = X86::edi;
-
-    static const RegisterID regT0 = X86::ebx;
-    static const RegisterID regT1 = X86::esi;
-
-    static const RegisterID returnRegister = X86::eax;
-#endif
-#if PLATFORM(X86_64)
-    static const RegisterID input = X86::edi;
-    static const RegisterID index = X86::esi;
-    static const RegisterID length = X86::edx;
-    static const RegisterID output = X86::ecx;
-
-    static const RegisterID regT0 = X86::eax;
-    static const RegisterID regT1 = X86::ebx;
-
-    static const RegisterID returnRegister = X86::eax;
+#if CPU(ARM)
+    static const RegisterID input = ARMRegisters::r0;
+    static const RegisterID index = ARMRegisters::r1;
+    static const RegisterID length = ARMRegisters::r2;
+    static const RegisterID output = ARMRegisters::r4;
+
+    static const RegisterID regT0 = ARMRegisters::r5;
+    static const RegisterID regT1 = ARMRegisters::r6;
+
+    static const RegisterID returnRegister = ARMRegisters::r0;
+#elif CPU(X86)
+    static const RegisterID input = X86Registers::eax;
+    static const RegisterID index = X86Registers::edx;
+    static const RegisterID length = X86Registers::ecx;
+    static const RegisterID output = X86Registers::edi;
+
+    static const RegisterID regT0 = X86Registers::ebx;
+    static const RegisterID regT1 = X86Registers::esi;
+
+    static const RegisterID returnRegister = X86Registers::eax;
+#elif CPU(X86_64)
+    static const RegisterID input = X86Registers::edi;
+    static const RegisterID index = X86Registers::esi;
+    static const RegisterID length = X86Registers::edx;
+    static const RegisterID output = X86Registers::ecx;
+
+    static const RegisterID regT0 = X86Registers::eax;
+    static const RegisterID regT1 = X86Registers::ebx;
+
+    static const RegisterID returnRegister = X86Registers::eax;
 #endif
 
     void optimizeAlternative(PatternAlternative* alternative)
 #endif
 
     void optimizeAlternative(PatternAlternative* alternative)
@@ -551,11 +549,11 @@ class RegexGenerator : private MacroAssembler {
         }
 
         if (mask) {
         }
 
         if (mask) {
-            load32(BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), character);
+            load32WithUnalignedHalfWords(BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), character);
             or32(Imm32(mask), character);
             state.jumpToBacktrack(branch32(NotEqual, character, Imm32(chPair | mask)), this);
         } else
             or32(Imm32(mask), character);
             state.jumpToBacktrack(branch32(NotEqual, character, Imm32(chPair | mask)), this);
         } else
-            state.jumpToBacktrack(branch32(NotEqual, BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), Imm32(chPair)), this);
+            state.jumpToBacktrack(branch32WithUnalignedHalfWords(NotEqual, BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), Imm32(chPair)), this);
     }
 
     void generatePatternCharacterFixed(TermGenerationState& state)
     }
 
     void generatePatternCharacterFixed(TermGenerationState& state)
@@ -1266,7 +1264,7 @@ class RegexGenerator : private MacroAssembler {
         // complex here in compilation, and in the common case we should end up coallescing the checks.
         //
         // FIXME: a nice improvement here may be to stop trying to match sooner, based on the least
         // complex here in compilation, and in the common case we should end up coallescing the checks.
         //
         // FIXME: a nice improvement here may be to stop trying to match sooner, based on the least
-        // of the minimum-alterantive-lengths.  E.g. if I have two alternatives of length 200 and 150,
+        // of the minimum-alternative-lengths.  E.g. if I have two alternatives of length 200 and 150,
         // and a string of length 100, we'll end up looping index from 0 to 100, checking whether there
         // is sufficient input to run either alternative (constantly failing).  If there had been only
         // one alternative, or if the shorter alternative had come first, we would have terminated
         // and a string of length 100, we'll end up looping index from 0 to 100, checking whether there
         // is sufficient input to run either alternative (constantly failing).  If there had been only
         // one alternative, or if the shorter alternative had come first, we would have terminated
@@ -1290,48 +1288,48 @@ class RegexGenerator : private MacroAssembler {
 
     void generateEnter()
     {
 
     void generateEnter()
     {
-#if PLATFORM(X86_64)
-        push(X86::ebp);
-        move(stackPointerRegister, X86::ebp);
-        push(X86::ebx);
-#elif PLATFORM(X86)
-        push(X86::ebp);
-        move(stackPointerRegister, X86::ebp);
+#if CPU(X86_64)
+        push(X86Registers::ebp);
+        move(stackPointerRegister, X86Registers::ebp);
+        push(X86Registers::ebx);
+#elif CPU(X86)
+        push(X86Registers::ebp);
+        move(stackPointerRegister, X86Registers::ebp);
         // TODO: do we need spill registers to fill the output pointer if there are no sub captures?
         // TODO: do we need spill registers to fill the output pointer if there are no sub captures?
-        push(X86::ebx);
-        push(X86::edi);
-        push(X86::esi);
+        push(X86Registers::ebx);
+        push(X86Registers::edi);
+        push(X86Registers::esi);
         // load output into edi (2 = saved ebp + return address).
     #if COMPILER(MSVC)
         // load output into edi (2 = saved ebp + return address).
     #if COMPILER(MSVC)
-        loadPtr(Address(X86::ebp, 2 * sizeof(void*)), input);
-        loadPtr(Address(X86::ebp, 3 * sizeof(void*)), index);
-        loadPtr(Address(X86::ebp, 4 * sizeof(void*)), length);
-        loadPtr(Address(X86::ebp, 5 * sizeof(void*)), output);
+        loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), input);
+        loadPtr(Address(X86Registers::ebp, 3 * sizeof(void*)), index);
+        loadPtr(Address(X86Registers::ebp, 4 * sizeof(void*)), length);
+        loadPtr(Address(X86Registers::ebp, 5 * sizeof(void*)), output);
     #else
     #else
-        loadPtr(Address(X86::ebp, 2 * sizeof(void*)), output);
+        loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), output);
     #endif
     #endif
-#elif PLATFORM_ARM_ARCH(7)
-        push(ARM::r4);
-        push(ARM::r5);
-        push(ARM::r6);
-        move(ARM::r3, output);
+#elif CPU(ARM)
+        push(ARMRegisters::r4);
+        push(ARMRegisters::r5);
+        push(ARMRegisters::r6);
+        move(ARMRegisters::r3, output);
 #endif
     }
 
     void generateReturn()
     {
 #endif
     }
 
     void generateReturn()
     {
-#if PLATFORM(X86_64)
-        pop(X86::ebx);
-        pop(X86::ebp);
-#elif PLATFORM(X86)
-        pop(X86::esi);
-        pop(X86::edi);
-        pop(X86::ebx);
-        pop(X86::ebp);
-#elif PLATFORM_ARM_ARCH(7)
-        pop(ARM::r6);
-        pop(ARM::r5);
-        pop(ARM::r4);
+#if CPU(X86_64)
+        pop(X86Registers::ebx);
+        pop(X86Registers::ebp);
+#elif CPU(X86)
+        pop(X86Registers::esi);
+        pop(X86Registers::edi);
+        pop(X86Registers::ebx);
+        pop(X86Registers::ebp);
+#elif CPU(ARM)
+        pop(ARMRegisters::r6);
+        pop(ARMRegisters::r5);
+        pop(ARMRegisters::r4);
 #endif
         ret();
     }
 #endif
         ret();
     }
@@ -1399,14 +1397,6 @@ void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const
     }
 }
 
     }
 }
 
-int executeRegex(RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output, int outputArraySize)
-{
-    if (JSRegExp* fallback = jitObject.getFallback())
-        return (jsRegExpExecute(fallback, input, length, start, output, outputArraySize) < 0) ? -1 : output[0];
-
-    return jitObject.execute(input, start, length, output);
-}
-
 }}
 
 #endif
 }}
 
 #endif
index 5b0df9dde0580051ddf7a27f105ddcbd28896698..935b9a3a18c18e51d1dbb71553d540bb97c99fd3 100644 (file)
@@ -37,7 +37,7 @@
 #include <pcre.h>
 struct JSRegExp; // temporary, remove when fallback is removed.
 
 #include <pcre.h>
 struct JSRegExp; // temporary, remove when fallback is removed.
 
-#if PLATFORM(X86) && !COMPILER(MSVC)
+#if CPU(X86) && !COMPILER(MSVC)
 #define YARR_CALL __attribute__ ((regparm (3)))
 #else
 #define YARR_CALL
 #define YARR_CALL __attribute__ ((regparm (3)))
 #else
 #define YARR_CALL
@@ -82,7 +82,14 @@ private:
 };
 
 void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase = false, bool multiline = false);
 };
 
 void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase = false, bool multiline = false);
-int executeRegex(RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output, int outputArraySize);
+
+inline int executeRegex(RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output, int outputArraySize)
+{
+    if (JSRegExp* fallback = jitObject.getFallback())
+        return (jsRegExpExecute(fallback, input, length, start, output, outputArraySize) < 0) ? -1 : output[0];
+
+    return jitObject.execute(input, start, length, output);
+}
 
 } } // namespace JSC::Yarr
 
 
 } } // namespace JSC::Yarr
 
index fb1b0ab8156bebddf0e0bf9a4e56f00957df8c06..dd7512d0b11c1231884077e03bab12e4d3225b7e 100644 (file)
@@ -57,7 +57,7 @@ struct CharacterRange {
     }
 };
 
     }
 };
 
-struct CharacterClass {
+struct CharacterClass : FastAllocBase {
     Vector<UChar> m_matches;
     Vector<CharacterRange> m_ranges;
     Vector<UChar> m_matchesUnicode;
     Vector<UChar> m_matches;
     Vector<CharacterRange> m_ranges;
     Vector<UChar> m_matchesUnicode;
@@ -137,7 +137,7 @@ struct PatternTerm {
 
     PatternTerm(unsigned spatternId)
         : type(TypeBackReference)
 
     PatternTerm(unsigned spatternId)
         : type(TypeBackReference)
-        , invertOrCapture(invertOrCapture)
+        , invertOrCapture(false)
     {
         subpatternId = spatternId;
         quantityType = QuantifierFixedCount;
     {
         subpatternId = spatternId;
         quantityType = QuantifierFixedCount;
@@ -181,7 +181,7 @@ struct PatternTerm {
     }
 };
 
     }
 };
 
-struct PatternAlternative {
+struct PatternAlternative : FastAllocBase {
     PatternAlternative(PatternDisjunction* disjunction)
         : m_parent(disjunction)
     {
     PatternAlternative(PatternDisjunction* disjunction)
         : m_parent(disjunction)
     {
@@ -205,7 +205,7 @@ struct PatternAlternative {
     bool m_hasFixedSize;
 };
 
     bool m_hasFixedSize;
 };
 
-struct PatternDisjunction {
+struct PatternDisjunction : FastAllocBase {
     PatternDisjunction(PatternAlternative* parent = 0)
         : m_parent(parent)
     {
     PatternDisjunction(PatternAlternative* parent = 0)
         : m_parent(parent)
     {