Reviewed by mjs.
authorggaren <ggaren@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 Feb 2006 06:42:01 +0000 (06:42 +0000)
committerggaren <ggaren@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 Feb 2006 06:42:01 +0000 (06:42 +0000)
        - Fixed <rdar://problem/4343730> Should switch ConstantValues (null,
        undefined, true, false) from JS objects to immediate values similar to
        SimpleNumber

        2.0% performance gain on my new super-accurate version of JS iBench.
        (I promise to land a version of it soon.)

        The gist of the change:
        (1) The SimpleNumber class (simple_number.h) is now the JSImmediate
        class (JSImmediate.h/.cpp), and it handles not only numbers but also
        null, undefined, true, and false.
        (2) JSImmediate provides convenience methods for the bit masking
        necessary to encode and decode immediate values.
        (3) ConstantValues, BooleanImp, NullImp, and UndefinedImp are gone.
        (4) JSCell no longer implements functions like getBoolean, because
        only a JSImmediate can be a boolean.
        (5) JSImmediate no longer uses ALWAYS_INLINE because there's no need,
        and ALWAYS_INLINE is a non-portable option of last resort.
        (6) Type is now JSType, and it resides in its own file, JSType.h.
        Since I was there, I did some header include sorting as part of this
        change.

        The rest pretty much explains itself.

        * JavaScriptCore.xcodeproj/project.pbxproj: Removed simple_number.h,
        added JSImmediate.h/.cpp.
        * bindings/c/c_instance.cpp:
        (KJS::Bindings::CInstance::defaultValue):
        * bindings/c/c_instance.h:
        * bindings/c/c_utility.cpp:
        (KJS::Bindings::convertValueToNPVariant):
        * bindings/jni/jni_instance.cpp:
        (JavaInstance::defaultValue):
        * bindings/jni/jni_instance.h:
        * bindings/jni/jni_jsobject.cpp:
        (JavaJSObject::convertValueToJObject):
        * bindings/objc/WebScriptObject.mm:
        (+[WebScriptObject _convertValueToObjcValue:originExecutionContext:executionContext:]):
        Standardized calls to use getXXX instead of hand-rolling JSValue
        functionality.
        * bindings/objc/objc_instance.h:
        * bindings/objc/objc_instance.mm:
        (ObjcInstance::getValueOfUndefinedField):
        (ObjcInstance::defaultValue):
        * bindings/objc/objc_runtime.h:
        * bindings/objc/objc_runtime.mm:
        (ObjcFallbackObjectImp::type):
        (ObjcFallbackObjectImp::defaultValue):
        * bindings/runtime.h:
        (KJS::Bindings::Instance::getValueOfUndefinedField):
        * bindings/runtime_object.cpp:
        (RuntimeObjectImp::defaultValue):
        * bindings/runtime_object.h:
        * kjs/JSImmediate.h: Added.
        (KJS::JSImmediate::isImmediate):
        (KJS::JSImmediate::isNumber):
        (KJS::JSImmediate::isBoolean):
        (KJS::JSImmediate::isUndefinedOrNull):
        (KJS::JSImmediate::fromDouble):
        (KJS::JSImmediate::toDouble):
        (KJS::JSImmediate::toBoolean):
        (KJS::JSImmediate::trueImmediate):
        (KJS::JSImmediate::falseImmediate):
        (KJS::JSImmediate::NaNImmediate):
        (KJS::JSImmediate::undefinedImmediate):
        (KJS::JSImmediate::nullImmediate):
        (KJS::JSImmediate::tag):
        (KJS::JSImmediate::unTag):
        (KJS::JSImmediate::getTag):
        (KJS::JSImmediate::):
        (KJS::JSImmediate::isIEEE):
        (KJS::JSImmediate::is32bit):
        (KJS::JSImmediate::is64bit):
        (KJS::JSImmediate::NanAsBits):
        (KJS::JSImmediate::zeroAsBits):
        (KJS::JSImmediate::oneAsBits):
        * kjs/JSLock.cpp:
        (KJS::JSLock::lock): Removed hack-o-rama to initialize ConstantValues.
        * kjs/JSType.h: Added.
        * kjs/collector.cpp:
        (KJS::Collector::protect):
        (KJS::Collector::unprotect):
        (KJS::Collector::collect):
        * kjs/internal.cpp:
        (KJS::StringImp::toPrimitive):
        (KJS::NumberImp::toPrimitive):
        (KJS::NumberImp::toBoolean):
        (KJS::GetterSetterImp::toPrimitive):
        * kjs/internal.h:
        (KJS::StringImp::type):
        (KJS::NumberImp::type):
        * kjs/object.cpp:
        (KJS::JSObject::type):
        (KJS::tryGetAndCallProperty): Replaced "Are you one of the six things
        I'm looking for?" test with "Are you not the one thing I'm not looking
        for" test.
        (KJS::JSObject::defaultValue):
        (KJS::JSObject::toPrimitive):
        * kjs/object.h:
        (KJS::GetterSetterImp::type):
        (KJS::JSValue::isObject):
        * kjs/operations.cpp:
        (KJS::equal):
        (KJS::strictEqual):
        (KJS::add):
        * kjs/reference.cpp:
        (KJS::Reference::deleteValue):
        * kjs/simple_number.h: Removed.
        * kjs/string_object.cpp:
        (StringInstance::getOwnPropertySlot): fixed indentation
        * kjs/value.cpp:
        (KJS::JSValue::toObject):
        (KJS::jsNumberCell): New function to quarantine a PIC branch -- allows
        us to inline jsNumber without adding PIC branches to callers.
        * kjs/value.h:
        (KJS::jsUndefined):
        (KJS::jsNull):
        (KJS::jsNaN):
        (KJS::jsBoolean):
        (KJS::jsNumber):
        (KJS::JSValue::downcast):
        (KJS::JSValue::isUndefinedOrNull):
        (KJS::JSValue::isBoolean):
        (KJS::JSValue::isNumber):
        (KJS::JSValue::isString):
        (KJS::JSValue::isObject):
        (KJS::JSValue::getBoolean):
        (KJS::JSValue::getNumber):
        (KJS::JSValue::getString):
        (KJS::JSValue::getObject):
        (KJS::JSValue::getUInt32):
        (KJS::JSValue::mark): Replaced !JSImmediate::is() test with assertion,
        resulting in a slight performance gain. Callers should always check
        !marked() before calling mark(), so it's impossible to call mark on
        a JSImmediate.
        (KJS::JSValue::marked):
        (KJS::JSValue::type):
        (KJS::JSValue::toPrimitive):
        (KJS::JSValue::toBoolean):
        (KJS::JSValue::toNumber):
        (KJS::JSValue::toString):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@12728 268f45cc-cd09-0410-ab3c-d52691b4dbfc

31 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/bindings/c/c_instance.cpp
JavaScriptCore/bindings/c/c_instance.h
JavaScriptCore/bindings/c/c_utility.cpp
JavaScriptCore/bindings/jni/jni_instance.cpp
JavaScriptCore/bindings/jni/jni_instance.h
JavaScriptCore/bindings/jni/jni_jsobject.cpp
JavaScriptCore/bindings/objc/WebScriptObject.mm
JavaScriptCore/bindings/objc/objc_instance.h
JavaScriptCore/bindings/objc/objc_instance.mm
JavaScriptCore/bindings/objc/objc_runtime.h
JavaScriptCore/bindings/objc/objc_runtime.mm
JavaScriptCore/bindings/runtime.h
JavaScriptCore/bindings/runtime_object.cpp
JavaScriptCore/bindings/runtime_object.h
JavaScriptCore/kjs/JSImmediate.cpp [new file with mode: 0644]
JavaScriptCore/kjs/JSImmediate.h [new file with mode: 0644]
JavaScriptCore/kjs/JSLock.cpp
JavaScriptCore/kjs/JSType.h [new file with mode: 0644]
JavaScriptCore/kjs/collector.cpp
JavaScriptCore/kjs/internal.cpp
JavaScriptCore/kjs/internal.h
JavaScriptCore/kjs/object.cpp
JavaScriptCore/kjs/object.h
JavaScriptCore/kjs/operations.cpp
JavaScriptCore/kjs/reference.cpp
JavaScriptCore/kjs/simple_number.h [deleted file]
JavaScriptCore/kjs/string_object.cpp
JavaScriptCore/kjs/value.cpp
JavaScriptCore/kjs/value.h

index 979fc22c586d2926754d057a653f1602d461dfca..d816deafacf2ffa588266d1dac659f2bd0ab3fe9 100644 (file)
@@ -1,3 +1,149 @@
+2006-02-09  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by mjs.
+
+        - Fixed <rdar://problem/4343730> Should switch ConstantValues (null, 
+        undefined, true, false) from JS objects to immediate values similar to
+        SimpleNumber
+
+        2.0% performance gain on my new super-accurate version of JS iBench.
+        (I promise to land a version of it soon.)
+
+        The gist of the change:
+        (1) The SimpleNumber class (simple_number.h) is now the JSImmediate
+        class (JSImmediate.h/.cpp), and it handles not only numbers but also 
+        null, undefined, true, and false. 
+        (2) JSImmediate provides convenience methods for the bit masking
+        necessary to encode and decode immediate values.
+        (3) ConstantValues, BooleanImp, NullImp, and UndefinedImp are gone.
+        (4) JSCell no longer implements functions like getBoolean, because
+        only a JSImmediate can be a boolean.
+        (5) JSImmediate no longer uses ALWAYS_INLINE because there's no need,
+        and ALWAYS_INLINE is a non-portable option of last resort.
+        (6) Type is now JSType, and it resides in its own file, JSType.h.
+        Since I was there, I did some header include sorting as part of this
+        change.
+
+        The rest pretty much explains itself.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj: Removed simple_number.h,
+        added JSImmediate.h/.cpp.
+        * bindings/c/c_instance.cpp:
+        (KJS::Bindings::CInstance::defaultValue):
+        * bindings/c/c_instance.h:
+        * bindings/c/c_utility.cpp:
+        (KJS::Bindings::convertValueToNPVariant):
+        * bindings/jni/jni_instance.cpp:
+        (JavaInstance::defaultValue):
+        * bindings/jni/jni_instance.h:
+        * bindings/jni/jni_jsobject.cpp:
+        (JavaJSObject::convertValueToJObject):
+        * bindings/objc/WebScriptObject.mm:
+        (+[WebScriptObject _convertValueToObjcValue:originExecutionContext:executionContext:]):
+        Standardized calls to use getXXX instead of hand-rolling JSValue 
+        functionality.
+        * bindings/objc/objc_instance.h:
+        * bindings/objc/objc_instance.mm:
+        (ObjcInstance::getValueOfUndefinedField):
+        (ObjcInstance::defaultValue):
+        * bindings/objc/objc_runtime.h:
+        * bindings/objc/objc_runtime.mm:
+        (ObjcFallbackObjectImp::type):
+        (ObjcFallbackObjectImp::defaultValue):
+        * bindings/runtime.h:
+        (KJS::Bindings::Instance::getValueOfUndefinedField):
+        * bindings/runtime_object.cpp:
+        (RuntimeObjectImp::defaultValue):
+        * bindings/runtime_object.h:
+        * kjs/JSImmediate.h: Added.
+        (KJS::JSImmediate::isImmediate):
+        (KJS::JSImmediate::isNumber):
+        (KJS::JSImmediate::isBoolean):
+        (KJS::JSImmediate::isUndefinedOrNull):
+        (KJS::JSImmediate::fromDouble):
+        (KJS::JSImmediate::toDouble):
+        (KJS::JSImmediate::toBoolean):
+        (KJS::JSImmediate::trueImmediate):
+        (KJS::JSImmediate::falseImmediate):
+        (KJS::JSImmediate::NaNImmediate):
+        (KJS::JSImmediate::undefinedImmediate):
+        (KJS::JSImmediate::nullImmediate):
+        (KJS::JSImmediate::tag):
+        (KJS::JSImmediate::unTag):
+        (KJS::JSImmediate::getTag):
+        (KJS::JSImmediate::):
+        (KJS::JSImmediate::isIEEE):
+        (KJS::JSImmediate::is32bit):
+        (KJS::JSImmediate::is64bit):
+        (KJS::JSImmediate::NanAsBits):
+        (KJS::JSImmediate::zeroAsBits):
+        (KJS::JSImmediate::oneAsBits):
+        * kjs/JSLock.cpp:
+        (KJS::JSLock::lock): Removed hack-o-rama to initialize ConstantValues.
+        * kjs/JSType.h: Added.
+        * kjs/collector.cpp:
+        (KJS::Collector::protect):
+        (KJS::Collector::unprotect):
+        (KJS::Collector::collect):
+        * kjs/internal.cpp:
+        (KJS::StringImp::toPrimitive):
+        (KJS::NumberImp::toPrimitive):
+        (KJS::NumberImp::toBoolean):
+        (KJS::GetterSetterImp::toPrimitive):
+        * kjs/internal.h:
+        (KJS::StringImp::type):
+        (KJS::NumberImp::type):
+        * kjs/object.cpp:
+        (KJS::JSObject::type):
+        (KJS::tryGetAndCallProperty): Replaced "Are you one of the six things
+        I'm looking for?" test with "Are you not the one thing I'm not looking
+        for" test.
+        (KJS::JSObject::defaultValue):
+        (KJS::JSObject::toPrimitive):
+        * kjs/object.h:
+        (KJS::GetterSetterImp::type):
+        (KJS::JSValue::isObject):
+        * kjs/operations.cpp:
+        (KJS::equal):
+        (KJS::strictEqual):
+        (KJS::add):
+        * kjs/reference.cpp:
+        (KJS::Reference::deleteValue):
+        * kjs/simple_number.h: Removed.
+        * kjs/string_object.cpp:
+        (StringInstance::getOwnPropertySlot): fixed indentation
+        * kjs/value.cpp:
+        (KJS::JSValue::toObject):
+        (KJS::jsNumberCell): New function to quarantine a PIC branch -- allows
+        us to inline jsNumber without adding PIC branches to callers.
+        * kjs/value.h:
+        (KJS::jsUndefined):
+        (KJS::jsNull):
+        (KJS::jsNaN):
+        (KJS::jsBoolean):
+        (KJS::jsNumber):
+        (KJS::JSValue::downcast):
+        (KJS::JSValue::isUndefinedOrNull):
+        (KJS::JSValue::isBoolean):
+        (KJS::JSValue::isNumber):
+        (KJS::JSValue::isString):
+        (KJS::JSValue::isObject):
+        (KJS::JSValue::getBoolean):
+        (KJS::JSValue::getNumber):
+        (KJS::JSValue::getString):
+        (KJS::JSValue::getObject):
+        (KJS::JSValue::getUInt32):
+        (KJS::JSValue::mark): Replaced !JSImmediate::is() test with assertion,
+        resulting in a slight performance gain. Callers should always check
+        !marked() before calling mark(), so it's impossible to call mark on
+        a JSImmediate.
+        (KJS::JSValue::marked):
+        (KJS::JSValue::type):
+        (KJS::JSValue::toPrimitive):
+        (KJS::JSValue::toBoolean):
+        (KJS::JSValue::toNumber):
+        (KJS::JSValue::toString):
+
 2006-02-06  Eric Seidel  <eseidel@apple.com>
 
         Add svn:ignore properties for visual studio internals.
index 103565125ebfcf70e54dbccc95175270c497aa51..3b0b66a6e290380e7e59e40d4a63a5999d9c087f 100644 (file)
 /* End PBXAggregateTarget section */
 
 /* Begin PBXBuildFile section */
+               14760864099C633800437128 /* JSImmediate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14760863099C633800437128 /* JSImmediate.cpp */; };
+               1483B58A099BC1950016E4F0 /* JSImmediate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1483B589099BC1950016E4F0 /* JSImmediate.h */; };
                148A1627095D16BB00666D0D /* ListRefPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 148A1626095D16BB00666D0D /* ListRefPtr.h */; };
+               14ABB36F099C076400E2A24F /* value.h in Headers */ = {isa = PBXBuildFile; fileRef = 14ABB36E099C076400E2A24F /* value.h */; };
+               14ABB455099C2A0F00E2A24F /* JSType.h in Headers */ = {isa = PBXBuildFile; fileRef = 14ABB454099C2A0F00E2A24F /* JSType.h */; };
                652C107F08DA7B1E0020887D /* protected_reference.h in Headers */ = {isa = PBXBuildFile; fileRef = 652C107E08DA7B1E0020887D /* protected_reference.h */; };
                6541BD7208E80A17002CBEE7 /* TCPageMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6E08E80A17002CBEE7 /* TCPageMap.h */; };
                6541BD7308E80A17002CBEE7 /* TCSpinLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6F08E80A17002CBEE7 /* TCSpinLock.h */; };
                932F5B590822A1C700736975 /* string_object.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8800255597D01FF60F7 /* string_object.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B5B0822A1C700736975 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8840255597D01FF60F7 /* types.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B5C0822A1C700736975 /* ustring.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8860255597D01FF60F7 /* ustring.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               932F5B5D0822A1C700736975 /* value.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8880255597D01FF60F7 /* value.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B600822A1C700736975 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = F68EBB8C0255D4C601FF60F7 /* config.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B610822A1C700736975 /* JavaScriptCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */; };
-               932F5B620822A1C700736975 /* simple_number.h in Headers */ = {isa = PBXBuildFile; fileRef = F50888B6030BB74C012A967E /* simple_number.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B630822A1C700736975 /* reference_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F54F0800030CD22001B5C2EB /* reference_list.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B640822A1C700736975 /* reference.h in Headers */ = {isa = PBXBuildFile; fileRef = F5341391030CEEB1018BE7F3 /* reference.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B650822A1C700736975 /* completion.h in Headers */ = {isa = PBXBuildFile; fileRef = F5BB2BC5030F772101FCFE1D /* completion.h */; settings = {ATTRIBUTES = (Private, ); }; };
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
+               14760863099C633800437128 /* JSImmediate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSImmediate.cpp; sourceTree = "<group>"; };
+               1483B589099BC1950016E4F0 /* JSImmediate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSImmediate.h; sourceTree = "<group>"; };
                148A1626095D16BB00666D0D /* ListRefPtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ListRefPtr.h; sourceTree = "<group>"; };
+               14ABB36E099C076400E2A24F /* value.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = value.h; sourceTree = "<group>"; };
+               14ABB454099C2A0F00E2A24F /* JSType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSType.h; sourceTree = "<group>"; };
                45E12D8806A49B0F00E9DF84 /* testkjs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = testkjs.cpp; sourceTree = "<group>"; tabWidth = 8; };
                5114F47B05E4426200D1BBBD /* runtime_root.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = runtime_root.cpp; path = bindings/runtime_root.cpp; sourceTree = "<group>"; tabWidth = 8; };
                5114F47C05E4426200D1BBBD /* runtime_root.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = runtime_root.h; path = bindings/runtime_root.h; sourceTree = "<group>"; tabWidth = 8; };
                93E26CF608B29A1C00F85226 /* pcre_get.c */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = pcre_get.c; path = pcre/pcre_get.c; sourceTree = "<group>"; tabWidth = 8; };
                93E26DDB08B2A4F400F85226 /* pcre_printint.c */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = pcre_printint.c; path = pcre/pcre_printint.c; sourceTree = "<group>"; tabWidth = 8; };
                93F1981A08245AAE001E9ABC /* keywords.table */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = text; path = keywords.table; sourceTree = "<group>"; tabWidth = 8; };
-               F50888B6030BB74C012A967E /* simple_number.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = simple_number.h; sourceTree = "<group>"; tabWidth = 8; };
                F5341390030CEEB1018BE7F3 /* reference.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reference.cpp; sourceTree = "<group>"; tabWidth = 8; };
                F5341391030CEEB1018BE7F3 /* reference.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = reference.h; sourceTree = "<group>"; tabWidth = 8; };
                F5341394030CF5F8018BE7F3 /* reference_list.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reference_list.cpp; sourceTree = "<group>"; tabWidth = 8; };
                F692A8850255597D01FF60F7 /* ustring.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ustring.cpp; sourceTree = "<group>"; tabWidth = 8; };
                F692A8860255597D01FF60F7 /* ustring.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ustring.h; sourceTree = "<group>"; tabWidth = 8; };
                F692A8870255597D01FF60F7 /* value.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = value.cpp; sourceTree = "<group>"; tabWidth = 8; };
-               F692A8880255597D01FF60F7 /* value.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = value.h; sourceTree = "<group>"; tabWidth = 8; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                                F692A87E0255597D01FF60F7 /* regexp.h */,
                                9374D3A7038D9D74008635CE /* scope_chain.h */,
                                9374D3A8038D9D74008635CE /* scope_chain.cpp */,
-                               F50888B6030BB74C012A967E /* simple_number.h */,
                                F692A87F0255597D01FF60F7 /* string_object.cpp */,
                                F692A8800255597D01FF60F7 /* string_object.h */,
                                F692A8840255597D01FF60F7 /* types.h */,
                                F692A8860255597D01FF60F7 /* ustring.h */,
                                F692A8850255597D01FF60F7 /* ustring.cpp */,
-                               F692A8880255597D01FF60F7 /* value.h */,
+                               14ABB36E099C076400E2A24F /* value.h */,
                                F692A8870255597D01FF60F7 /* value.cpp */,
+                               1483B589099BC1950016E4F0 /* JSImmediate.h */,
+                               14760863099C633800437128 /* JSImmediate.cpp */,
+                               14ABB454099C2A0F00E2A24F /* JSType.h */,
                        );
                        name = Classes;
                        sourceTree = "<group>";
                                932F5B590822A1C700736975 /* string_object.h in Headers */,
                                932F5B5B0822A1C700736975 /* types.h in Headers */,
                                932F5B5C0822A1C700736975 /* ustring.h in Headers */,
-                               932F5B5D0822A1C700736975 /* value.h in Headers */,
                                932F5B600822A1C700736975 /* config.h in Headers */,
                                932F5B610822A1C700736975 /* JavaScriptCorePrefix.h in Headers */,
-                               932F5B620822A1C700736975 /* simple_number.h in Headers */,
                                932F5B630822A1C700736975 /* reference_list.h in Headers */,
                                932F5B640822A1C700736975 /* reference.h in Headers */,
                                932F5B650822A1C700736975 /* completion.h in Headers */,
                                9303F568099118FA00AD71B8 /* OwnPtr.h in Headers */,
                                9303F56A0991190000AD71B8 /* Noncopyable.h in Headers */,
                                9303F5A509911A5800AD71B8 /* OwnArrayPtr.h in Headers */,
+                               1483B58A099BC1950016E4F0 /* JSImmediate.h in Headers */,
+                               14ABB36F099C076400E2A24F /* value.h in Headers */,
+                               14ABB455099C2A0F00E2A24F /* JSType.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                6541BD7408E80A17002CBEE7 /* TCSystemAlloc.cpp in Sources */,
                                65DFC93308EA173A00F7300B /* HashTable.cpp in Sources */,
                                65EA4C9B092AF9E20093D800 /* JSLock.cpp in Sources */,
+                               14760864099C633800437128 /* JSImmediate.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 6586075511746aacb5d98d60f2b7f19cc7c681c7..b0e3a7aadf9eed29abc0f2dc63003835195cd98a 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
-#include "config.h"
-#include <c_class.h>
-#include <c_instance.h>
-#include <c_runtime.h>
-#include <c_utility.h>
 
-#include <JavaScriptCore/npruntime_impl.h>
-#include <JavaScriptCore/npruntime_priv.h>
+#include "c_class.h"
+#include "c_instance.h"
+#include "c_runtime.h"
+#include "c_utility.h"
+#include "config.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
 
 #ifdef NDEBUG
 #define C_LOG(formatAndArgs...) ((void)0)
@@ -189,7 +189,7 @@ JSValue *CInstance::invokeDefaultMethod (ExecState *exec, const List &args)
 }
 
 
-JSValue *CInstance::defaultValue (Type hint) const
+JSValue *CInstance::defaultValue (JSType hint) const
 {
     if (hint == StringType) {
         return stringValue();
index 24b16c68900407ab3f6611d76b5563cd8ed2c406..f2b7b721a61b6c3fad4b32805599b36397c06a7b 100644 (file)
@@ -25,9 +25,9 @@
 #ifndef _BINDINGS_C_INSTANCE_H_
 #define _BINDINGS_C_INSTANCE_H_
 
-#include <npruntime.h>
-
-#include <runtime.h>
+#include "JSType.h"
+#include "npruntime.h"
+#include "runtime.h"
 
 namespace KJS {
 
@@ -52,7 +52,7 @@ public:
     virtual void end();
     
     virtual JSValue *valueOf() const;
-    virtual JSValue *defaultValue (KJS::Type hint) const;
+    virtual JSValue *defaultValue (JSType hint) const;
 
     virtual JSValue *invokeMethod (ExecState *exec, const MethodList &method, const List &args);
     virtual JSValue *invokeDefaultMethod (ExecState *exec, const List &args);
index 11a6d5bb302323c35c75e7ef0720a5855178c0de..f185c3b4237cbbfb6c0b8d48ce8fef82770ebbd7 100644 (file)
@@ -25,8 +25,9 @@
  */
 
 #include "config.h"
-#include "c_utility.h"
 
+#include "JSType.h"
+#include "c_utility.h"
 #include "c_instance.h" 
 #include "npruntime_impl.h"
 #include "npruntime_priv.h"
@@ -77,7 +78,7 @@ void coerceValueToNPVariantStringType(ExecState *exec, JSValue *value, NPVariant
 // Variant value must be released with NPReleaseVariantValue()
 void convertValueToNPVariant(ExecState *exec, JSValue *value, NPVariant *result)
 {
-    Type type = value->type();
+    JSType type = value->type();
     
     if (type == StringType) {
         UString ustring = value->toString(exec);
index 999a39bb51a8d6ed25e850675977322aa23cf785..65235a95759ea8266bc2c48f643558fba6a57dfd 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 #include "config.h"
-#include <jni_class.h>
-#include <jni_instance.h>
-#include <jni_runtime.h>
-#include <jni_utility.h>
-#include <runtime_object.h>
-#include <runtime_root.h>
+
+#include "jni_class.h"
+#include "jni_instance.h"
+#include "jni_runtime.h"
+#include "jni_utility.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
 
 #ifdef NDEBUG
 #define JS_LOG(formatAndArgs...) ((void)0)
@@ -300,7 +301,7 @@ JSValue *JavaInstance::invokeDefaultMethod (ExecState *exec, const List &args)
 }
 
 
-JSValue *JavaInstance::defaultValue (Type hint) const
+JSValue *JavaInstance::defaultValue (JSType hint) const
 {
     if (hint == StringType) {
         return stringValue();
index 971a501e2b72f46800b4ce00daa3f5c368f3349d..937af8963bf8b91fdfe84b3227482ecb639af653 100644 (file)
 #ifndef _JNI_INSTANCE_H_
 #define _JNI_INSTANCE_H_
 
-#include <CoreFoundation/CoreFoundation.h>
+#include "config.h"
+
+#include "runtime.h"
 
+#include <CoreFoundation/CoreFoundation.h>
 #include <JavaVM/jni.h>
 
-#include <JavaScriptCore/runtime.h>
 
 namespace KJS {
 
@@ -74,7 +76,7 @@ public:
     virtual void end();
     
     virtual JSValue *valueOf() const;
-    virtual JSValue *defaultValue (Type hint) const;
+    virtual JSValue *defaultValue (JSType hint) const;
 
     virtual JSValue *invokeMethod (ExecState *exec, const MethodList &method, const List &args);
     virtual JSValue *invokeDefaultMethod (ExecState *exec, const List &args);
index 9cca74e135f7c3c73ca4a55e495fbbeca611d179..e688ecb65a569c73596d250bdbe913acef720680 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 #include "config.h"
-#include <CoreFoundation/CoreFoundation.h>
 
-#include <assert.h>
+#include "identifier.h"
+#include "internal.h"
+#include "interpreter.h"
+#include "list.h"
+#include "jni_jsobject.h"
+#include "jni_runtime.h"
+#include "jni_utility.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
 
-#include <identifier.h>
-#include <internal.h>
-#include <interpreter.h>
-#include <list.h>
-#include <jni_jsobject.h>
-#include <jni_runtime.h>
-#include <jni_utility.h>
-#include <runtime_object.h>
-#include <runtime_root.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <assert.h>
 
 using namespace KJS::Bindings;
 using namespace KJS;
@@ -327,7 +327,7 @@ jobject JavaJSObject::convertValueToJObject (JSValue *value) const
     // Java instance -> Java instance
     // Everything else -> JavaJSObject
     
-    Type type = value->type();
+    JSType type = value->type();
     if (type == NumberType) {
         jclass JSObjectClass = env->FindClass ("java/lang/Double");
         jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(D)V");
index ca9ae8174535fde52b33b3e7dae738961a97f6e5..dfed3910064d6011fe779a835f93c73b1ebf7c4e 100644 (file)
@@ -418,9 +418,7 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
            return (id)intepreter->createLanguageInstanceForValue (exec, Instance::ObjectiveCLanguage, value->toObject(exec), originExecutionContext, executionContext);
     } else if (value->isString()) {
         // JS String --> NSString
-        StringImp *s = static_cast<StringImp*>(value);
-        UString u = s->value();
-        
+        UString u = value->getString();
         NSString *string = [NSString stringWithCharacters:(const unichar*)u.data() length:u.size()];
         return string;
     } else if (value->isNumber())
@@ -428,7 +426,7 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
         return [NSNumber numberWithDouble:value->getNumber()];
     else if (value->isBoolean())
         // JS Boolean --> NSNumber
-        return [NSNumber numberWithBool:static_cast<BooleanImp*>(value)->value()];
+        return [NSNumber numberWithBool:value->getBoolean()];
     else if (value->isUndefined())
         // JS Undefined --> WebUndefined
         return [WebUndefined undefined];
index 3dacb1b677ea8af434d46bc61a92bf5c0dc69570..7a9bbd5f047f7c3e3b1ee099434c12f7b67f2c6c 100644 (file)
@@ -54,7 +54,7 @@ public:
     virtual void end();
     
     virtual JSValue *valueOf() const;
-    virtual JSValue *defaultValue (Type hint) const;
+    virtual JSValue *defaultValue (JSType hint) const;
 
     virtual JSValue *invokeMethod (ExecState *exec, const MethodList &method, const List &args);
     virtual JSValue *invokeDefaultMethod (ExecState *exec, const List &args);
@@ -64,7 +64,7 @@ public:
     virtual void setValueOfUndefinedField (ExecState *exec, const Identifier &property, JSValue *aValue);
     
     virtual JSValue *ObjcInstance::getValueOfField (ExecState *exec, const Field *aField) const;
-    virtual JSValue *getValueOfUndefinedField (ExecState *exec, const Identifier &property, Type hint) const;
+    virtual JSValue *getValueOfUndefinedField (ExecState *exec, const Identifier &property, JSType hint) const;
 
     ObjectStructPtr getObject() const { return _instance; }
     
index 494c2b01ec06df204960e8569330fd2be3557a2f..8fc90f822d549b46f4846711eb84e4bc96ca4fe5 100644 (file)
@@ -332,7 +332,7 @@ JSValue *ObjcInstance::getValueOfField (ExecState *exec, const Field *aField) co
     return aField->valueFromInstance (exec, this);
 }
 
-JSValue *ObjcInstance::getValueOfUndefinedField (ExecState *exec, const Identifier &property, Type hint) const
+JSValue *ObjcInstance::getValueOfUndefinedField (ExecState *exec, const Identifier &property, JSType hint) const
 {
     JSValue *volatile result = jsUndefined();
     
@@ -360,7 +360,7 @@ JSValue *ObjcInstance::getValueOfUndefinedField (ExecState *exec, const Identifi
     return result;
 }
 
-JSValue *ObjcInstance::defaultValue (Type hint) const
+JSValue *ObjcInstance::defaultValue (JSType hint) const
 {
     if (hint == StringType) {
         return stringValue();
index 6d9f74c5a646bb15cbe136e2e399162c35693b27..f2643b78d682ab9554207767957b0f58f04f72e3 100644 (file)
@@ -167,9 +167,9 @@ public:
     virtual bool implementsCall() const;
     virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
     virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
-    virtual JSValue *defaultValue(ExecState *exec, Type hint) const;
+    virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
 
-    virtual Type type() const;
+    virtual JSType type() const;
     virtual bool toBoolean(ExecState *exec) const;
 
 private:
index 9f550f7e0b5671e0834c1775f3e86b985d18cc80..81cac2715ca9823a2f9ce338f16a07ab7e8b592b 100644 (file)
@@ -277,7 +277,7 @@ bool ObjcFallbackObjectImp::canPut(ExecState *exec, const Identifier &propertyNa
 }
 
 
-Type ObjcFallbackObjectImp::type() const
+JSType ObjcFallbackObjectImp::type() const
 {
     id targetObject = _instance->getObject();
     
@@ -332,7 +332,7 @@ bool ObjcFallbackObjectImp::deleteProperty(ExecState *exec,
     return false;
 }
 
-JSValue *ObjcFallbackObjectImp::defaultValue(ExecState *exec, Type hint) const
+JSValue *ObjcFallbackObjectImp::defaultValue(ExecState *exec, JSType hint) const
 {
     return _instance->getValueOfUndefinedField(exec, _item, hint);
 }
index 6aebd72e7a09698632bbd0d25359ac2ab2176acb..a01abc16327ecbb89ec53a4990aff0960fe1bcd4 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef JAVASCRIPTCORE_BINDINGS_RUNTIME_H
 #define JAVASCRIPTCORE_BINDINGS_RUNTIME_H
 
+#include "JSType.h"
 #include "value.h"
 
 namespace KJS  {
@@ -153,7 +154,7 @@ public:
     virtual Class *getClass() const = 0;
     
     virtual JSValue* getValueOfField(ExecState*, const Field*) const;
-    virtual JSValue* getValueOfUndefinedField(ExecState*, const Identifier& property, Type hint) const { return jsUndefined(); }
+    virtual JSValue* getValueOfUndefinedField(ExecState*, const Identifier& property, JSType hint) const { return jsUndefined(); }
     virtual void setValueOfField(ExecState*, const Field*, JSValue*) const;
     virtual bool supportsSetValueOfUndefinedField() { return false; }
     virtual void setValueOfUndefinedField(ExecState*, const Identifier& property, JSValue*) {}
@@ -161,7 +162,7 @@ public:
     virtual JSValue* invokeMethod(ExecState*, const MethodList&, const List& args) = 0;
     virtual JSValue* invokeDefaultMethod(ExecState*, const List& args) = 0;
     
-    virtual JSValue* defaultValue(Type hint) const = 0;
+    virtual JSValue* defaultValue(JSType hint) const = 0;
     
     virtual JSValue* valueOf() const { return jsString(getClass()->name()); }
     
index 47bc7f9bf6b9a24937d995c21cc5cdd0f97b9ddb..d308ae9e36b4f2febb0004e611fd4a8c3dfd389f 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #include "config.h"
+
 #include "error_object.h"
 #include "function.h"
 #include "interpreter.h"
@@ -188,7 +189,7 @@ bool RuntimeObjectImp::deleteProperty(ExecState *exec,
     return false;
 }
 
-JSValue *RuntimeObjectImp::defaultValue(ExecState *exec, Type hint) const
+JSValue *RuntimeObjectImp::defaultValue(ExecState *exec, JSType hint) const
 {
     JSValue *result;
     
index 97c11a43ce5c866507998f096f946850efea8153..c6855f832f03a19ecc11bf5cbc1c2c61a8018edf 100644 (file)
@@ -44,7 +44,7 @@ public:
     virtual bool canPut(ExecState *exec, const Identifier &propertyName) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None);
     virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
-    virtual JSValue *defaultValue(ExecState *exec, Type hint) const;
+    virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
     virtual bool implementsCall() const;
     virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
     
diff --git a/JavaScriptCore/kjs/JSImmediate.cpp b/JavaScriptCore/kjs/JSImmediate.cpp
new file mode 100644 (file)
index 0000000..d324850
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (C) 2003-2006 Apple Computer, Inc
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "JSImmediate.h"
+#include "kxmlcore/Assertions.h"
+#include "object.h"
+#include "value.h"
+
+namespace KJS {
+
+JSObject *JSImmediate::toObject(const JSValue *v, ExecState *exec)
+{
+    assert(is(v));
+    if (v == jsNull())
+        return throwError(exec, TypeError, "Null value");
+    else if (v == jsUndefined())
+        return throwError(exec, TypeError, "Undefined value");
+    else if (isBoolean(v)) {
+        List args;
+        args.append(const_cast<JSValue *>(v));
+        return exec->lexicalInterpreter()->builtinBoolean()->construct(exec, args);
+    } else {
+        ASSERT(isNumber(v));
+        List args;
+        args.append(const_cast<JSValue *>(v));
+        return exec->lexicalInterpreter()->builtinNumber()->construct(exec, args);
+    }
+}
+
+UString JSImmediate::toString(const JSValue *v)
+{
+    ASSERT(isImmediate(v));
+    
+    if (v == jsNull())
+        return "null";
+    else if (v == jsUndefined())
+        return "undefined";
+    else if (v == jsBoolean(true))
+        return "true";
+    else if (v == jsBoolean(false))
+        return "false";
+    else {
+        assert(isNumber(v));
+        double d = toDouble(v);
+        if (d == 0.0) // +0.0 or -0.0
+            return "0";
+        return UString::from(d);
+    }
+}
+
+JSType JSImmediate::type(const JSValue *v)
+{
+    ASSERT(isImmediate(v));
+    
+    uintptr_t tag = getTag(v);
+    if (tag == UndefinedType)
+        return v == jsUndefined() ? UndefinedType : NullType;
+    return static_cast<JSType>(tag);
+}
+
+} // namespace KJS
diff --git a/JavaScriptCore/kjs/JSImmediate.h b/JavaScriptCore/kjs/JSImmediate.h
new file mode 100644 (file)
index 0000000..3d7a786
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (C) 2003-2006 Apple Computer, Inc
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KJS_JS_IMMEDIATE_H
+#define KJS_JS_IMMEDIATE_H
+
+#include "JSType.h"
+#include "kxmlcore/Assertions.h"
+#include <stdlib.h> // for abort()
+
+namespace KJS {
+
+class JSValue;
+class ExecState;
+class JSObject;
+class UString;
+
+/*
+ * A JSValue * is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged 
+ * IEEE floating point bit pattern masquerading as a pointer). The low two bits in a JSValue * are available 
+ * for type tagging because allocator alignment guarantees they will be 00 in cell pointers.
+ *
+ * For example, on a 32 bit system:
+ *
+ * JSCell *:      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                 00
+ *               [ high 30 bits: pointer address ]  [ low 2 bits -- always 0 ]
+ *
+ * JSImmediate:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                 TT
+ *             [ high 30 bits: IEEE encoded float ] [ low 2 bits -- type tag ]
+ *
+ * The bit "payload" (the hight 30 bits) of a non-numeric immediate is its numeric equivalent. For example, 
+ * the payload of null is 0.0. This makes JSValue::toNumber() a simple bitmask for all immediates.
+ *
+ * Notice that the JSType value of NullType is 4, which requires 3 bits to encode. Since we only have 2 bits 
+ * available for type tagging, we tag the null immediate with UndefinedType, and JSImmediate::type() has 
+ * to sort them out. Null and Undefined don't otherwise get confused because the numeric value of Undefined is 
+ * NaN, not 0.0.
+ */
+
+class JSImmediate {
+public:
+    static bool isImmediate(const JSValue *v)
+    {
+        return getTag(v) != 0;
+    }
+    
+    static bool isNumber(const JSValue *v)
+    {
+        return (getTag(v) == NumberType);
+    }
+    
+    static bool isBoolean(const JSValue *v)
+    {
+        return (getTag(v) == BooleanType);
+    }
+    
+    // Since we have room for only 3 unique tags, null and undefined have to share.
+    static bool isUndefinedOrNull(const JSValue *v)
+    {
+        return (getTag(v) == UndefinedType);
+    }
+
+    static JSValue *fromDouble(double d)
+    {
+        if (is32bit()) {
+            FloatUnion floatUnion;
+            floatUnion.asFloat = d;
+            
+            // check for data loss from tagging
+            if ((floatUnion.asBits & TagMask) != 0)
+              return 0;
+            
+            // check for data loss from conversion to float
+            DoubleUnion doubleUnion1, doubleUnion2;
+            doubleUnion1.asDouble = floatUnion.asFloat;
+            doubleUnion2.asDouble = d;
+            if (doubleUnion1.asBits != doubleUnion2.asBits)
+                return 0;
+            
+            return tag(floatUnion.asBits, NumberType);
+        } else if (is64bit()) {
+            DoubleUnion doubleUnion;
+            doubleUnion.asDouble = d;
+            
+            // check for data loss from tagging
+            if ((doubleUnion.asBits & TagMask) != 0)
+                return 0;
+
+            return tag(doubleUnion.asBits, NumberType);
+        } else {
+            // could just return 0 here, but nicer to be explicit about not supporting the platform well
+            abort();
+        }
+    }
+    
+    static double toDouble(const JSValue *v)
+    {
+        ASSERT(isImmediate(v));
+        
+        if (is32bit()) {
+            FloatUnion floatUnion;
+            floatUnion.asBits = unTag(v);
+            return floatUnion.asFloat;
+        } else if (is64bit()) {
+            DoubleUnion doubleUnion;
+            doubleUnion.asBits = unTag(v);
+            return doubleUnion.asDouble;
+        } else
+            abort();
+    }
+
+    static bool toBoolean(const JSValue *v)
+    {
+        ASSERT(isImmediate(v));
+        
+        uintptr_t bits = unTag(v);
+        if ((bits << 1) == 0) // -0.0 has the sign bit set
+            return false;
+
+        return bits != NanAsBits();
+    }
+    
+    static JSObject *toObject(const JSValue *, ExecState *);
+    static UString toString(const JSValue *);
+    static JSType type(const JSValue *);
+    
+    // It would nice just to use fromDouble() to create these values, but that would prevent them from
+    // turning into compile-time constants.
+    static JSValue *trueImmediate() { return tag(oneAsBits(), BooleanType); }
+    static JSValue *falseImmediate() { return tag(zeroAsBits(), BooleanType); }
+    static JSValue *NaNImmediate() { return tag(NanAsBits(), NumberType); }
+    static JSValue *undefinedImmediate() { return tag(NanAsBits(), UndefinedType); }
+    static JSValue *nullImmediate() { return tag(zeroAsBits(), UndefinedType); }
+    
+private:
+    static const uintptr_t TagMask = 3; // type tags are 2 bits long
+    
+    static JSValue *tag(uintptr_t bits, uintptr_t tag)
+    {
+        return reinterpret_cast<JSValue *>(bits | tag);
+    }
+    
+    static uintptr_t unTag(const JSValue *v)
+    {
+        return reinterpret_cast<uintptr_t>(v) & ~TagMask;
+    }
+    
+    static uintptr_t getTag(const JSValue *v)
+    {
+        return reinterpret_cast<uintptr_t>(v) & TagMask;
+    }
+    
+    // NOTE: With f-strict-aliasing enabled, unions are the only safe way to do type masquerading.
+
+    union FloatUnion {
+        u_int32_t asBits;
+        float     asFloat;
+    };
+
+    union DoubleUnion {
+        u_int64_t asBits;
+        double    asDouble;
+    };
+
+    // IEEE compliant floating point
+    static bool isIEEE()
+    {
+        return sizeof(float) == sizeof(u_int32_t) &&
+               sizeof(double) == sizeof(u_int64_t);
+    }
+        
+    // 32 bit systems
+    static bool is32bit() 
+    {
+        return isIEEE() && sizeof(uintptr_t) == sizeof(u_int32_t);
+    }
+
+    // 64 bit systems
+    static bool is64bit()
+    {
+        return isIEEE() && sizeof(uintptr_t) == sizeof(u_int64_t);
+    }
+
+    static uintptr_t NanAsBits()
+    {
+        const u_int32_t NaN32AsBits = 0x7fc00000;
+        const u_int64_t NaN64AsBits = 0x7ff80000ULL << 32;
+
+        if (JSImmediate::is32bit())
+            return NaN32AsBits;
+        else if (JSImmediate::is64bit())
+            return NaN64AsBits;
+        else
+            abort();
+    }
+
+    static uintptr_t zeroAsBits()
+    {
+        return 0x0;
+    }
+
+    static uintptr_t oneAsBits()
+    {
+        const u_int32_t One32AsBits = 0x3f800000;
+        const u_int64_t One64AsBits = 0x3ff00000ULL << 32;
+
+        if (JSImmediate::is32bit())
+            return One32AsBits;
+        else if (JSImmediate::is64bit())
+            return One64AsBits;
+        else
+            abort();
+    }
+};
+
+} // namespace KJS
+
+#endif
index 7e3eb14214f8d2c00814aa5bafcb05a0262f69c9..123ddfa36ca7e754a19158ac7c8baaed6d98b990 100644 (file)
@@ -49,12 +49,6 @@ void JSLock::lock()
   pthread_mutex_lock(&interpreterLock);
   interpreterLockCount++;
   Collector::registerThread();
-
-  // FIXME: Hack-o-rama. To prevent construction of a global object with a null prototype (4342216),
-  // we need to intialize our constants before the first object is constructed. InterpreterImp::lock()
-  // is a good place to do this because you have to call it before doing any allocations. Once we change our 
-  // implementation to use immediate values, we should remove this code.
-  ConstantValues::initIfNeeded();
 }
 
 void JSLock::unlock()
@@ -71,11 +65,6 @@ const int interpreterLockCount = 1;
 
 void JSLock::lock()
 {
-  // FIXME: Hack-o-rama. To prevent construction of a global object with a null prototype (4342216),
-  // we need to intialize our constants before the first object is constructed. InterpreterImp::lock()
-  // is a good place to do this because you have to call it before doing any allocations. Once we change our 
-  // implementation to use immediate values, we should remove this code.
-  ConstantValues::initIfNeeded();
 }
 
 void JSLock::unlock()
diff --git a/JavaScriptCore/kjs/JSType.h b/JavaScriptCore/kjs/JSType.h
new file mode 100644 (file)
index 0000000..397e306
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (C) 2006 Apple Computer, Inc
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KJS_JSTYPE_H
+#define KJS_JSTYPE_H
+
+/**
+ * Primitive types
+ */
+enum JSType {
+    UnspecifiedType   = 0,
+    NumberType        = 1,
+    BooleanType       = 2,
+    UndefinedType     = 3,
+    NullType          = 4,
+    StringType        = 5,
+    ObjectType        = 6,
+    GetterSetterType  = 7
+};
+
+#endif
index 9222ea7da3f92e724e74e1aef78c2e2520b00563..a239f7758f606e3ef2919c5e0591e51b000feb0f 100644 (file)
@@ -407,7 +407,7 @@ void Collector::protect(JSValue *k)
     assert(k);
     assert(JSLock::lockCount() > 0);
 
-    if (SimpleNumber::is(k))
+    if (JSImmediate::isImmediate(k))
       return;
 
     protectedValues().add(k->downcast());
@@ -418,7 +418,7 @@ void Collector::unprotect(JSValue *k)
     assert(k);
     assert(JSLock::lockCount() > 0);
 
-    if (SimpleNumber::is(k))
+    if (JSImmediate::isImmediate(k))
       return;
 
     protectedValues().remove(k->downcast());
@@ -447,7 +447,6 @@ bool Collector::collect()
       scr = scr->next;
     } while (scr != InterpreterImp::s_hook);
   }
-  ConstantValues::mark();
 
   // MARK: first mark all referenced objects recursively starting out from the set of root objects
 
index 6462efc2fd11a84af93b37bd4b8cad2936445dde..3dc5dc4eca610ceace3b1ec34317be8e452f5251 100644 (file)
@@ -74,92 +74,9 @@ namespace KJS {
 #define copysign _copysign
 #endif
 
-// ------------------------------ UndefinedImp ---------------------------------
-
-JSValue *UndefinedImp::toPrimitive(ExecState *, Type) const
-{
-  return const_cast<UndefinedImp *>(this);
-}
-
-bool UndefinedImp::toBoolean(ExecState *) const
-{
-  return false;
-}
-
-double UndefinedImp::toNumber(ExecState *) const
-{
-  return NaN;
-}
-
-UString UndefinedImp::toString(ExecState *) const
-{
-  return "undefined";
-}
-
-JSObject *UndefinedImp::toObject(ExecState *exec) const
-{
-  return throwError(exec, TypeError, "Undefined value");
-}
-
-// ------------------------------ NullImp --------------------------------------
-
-JSValue *NullImp::toPrimitive(ExecState *, Type) const
-{
-  return const_cast<NullImp *>(this);
-}
-
-bool NullImp::toBoolean(ExecState *) const
-{
-  return false;
-}
-
-double NullImp::toNumber(ExecState *) const
-{
-  return 0.0;
-}
-
-UString NullImp::toString(ExecState *) const
-{
-  return "null";
-}
-
-JSObject *NullImp::toObject(ExecState *exec) const
-{
-  return throwError(exec, TypeError, "Null value");
-}
-
-// ------------------------------ BooleanImp -----------------------------------
-
-JSValue *BooleanImp::toPrimitive(ExecState *, Type) const
-{
-  return const_cast<BooleanImp *>(this);
-}
-
-bool BooleanImp::toBoolean(ExecState *) const
-{
-  return val;
-}
-
-double BooleanImp::toNumber(ExecState *) const
-{
-  return val ? 1.0 : 0.0;
-}
-
-UString BooleanImp::toString(ExecState *) const
-{
-  return val ? "true" : "false";
-}
-
-JSObject *BooleanImp::toObject(ExecState *exec) const
-{
-  List args;
-  args.append(const_cast<BooleanImp*>(this));
-  return static_cast<JSObject *>(exec->lexicalInterpreter()->builtinBoolean()->construct(exec,args));
-}
-
 // ------------------------------ StringImp ------------------------------------
 
-JSValue *StringImp::toPrimitive(ExecState *, Type) const
+JSValue *StringImp::toPrimitive(ExecState *, JSType) const
 {
   return const_cast<StringImp *>(this);
 }
@@ -186,14 +103,14 @@ JSObject *StringImp::toObject(ExecState *exec) const
 
 // ------------------------------ NumberImp ------------------------------------
 
-JSValue *NumberImp::toPrimitive(ExecState *, Type) const
+JSValue *NumberImp::toPrimitive(ExecState *, JSType) const
 {
   return const_cast<NumberImp *>(this);
 }
 
 bool NumberImp::toBoolean(ExecState *) const
 {
-  return !((val == 0) /* || (iVal() == N0) */ || isNaN(val));
+  return val < 0.0 || val > 0.0; // false for NaN
 }
 
 double NumberImp::toNumber(ExecState *) const
@@ -215,6 +132,8 @@ JSObject *NumberImp::toObject(ExecState *exec) const
   return static_cast<JSObject *>(exec->lexicalInterpreter()->builtinNumber()->construct(exec,args));
 }
 
+// FIXME: We can optimize this to work like JSValue::getUInt32. I'm ignoring it for now
+// because it never shows up on profiles.
 bool NumberImp::getUInt32(uint32_t& uint32) const
 {
   uint32 = (uint32_t)val;
@@ -230,7 +149,7 @@ void GetterSetterImp::mark()
         setter->mark();
 }
 
-JSValue *GetterSetterImp::toPrimitive(ExecState *exec, Type type) const
+JSValue *GetterSetterImp::toPrimitive(ExecState *exec, JSType) const
 {
     assert(false);
     return jsNull();
index 534cb3762928435a9f1360797c941493f8951051..87bb0761c6a8bfe88b56ec809a6e1d3dc8e75840 100644 (file)
 #ifndef INTERNAL_H
 #define INTERNAL_H
 
-#include "ustring.h"
+#include "JSType.h"
+#include "interpreter.h"
 #include "object.h"
 #include "protect.h"
-#include "types.h"
-#include "interpreter.h"
 #include "scope_chain.h"
+#include "types.h"
+#include "ustring.h"
+
 #include <kxmlcore/Noncopyable.h>
 #include <kxmlcore/RefPtr.h>
 
@@ -49,53 +51,14 @@ namespace KJS {
   //                            Primitive impls
   // ---------------------------------------------------------------------------
 
-  class UndefinedImp : public JSCell {
-  public:
-    Type type() const { return UndefinedType; }
-
-    JSValue *toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
-    bool toBoolean(ExecState *exec) const;
-    double toNumber(ExecState *exec) const;
-    UString toString(ExecState *exec) const;
-    JSObject *toObject(ExecState *exec) const;
-  };
-
-  class NullImp : public JSCell {
-  public:
-    Type type() const { return NullType; }
-
-    JSValue *toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
-    bool toBoolean(ExecState *exec) const;
-    double toNumber(ExecState *exec) const;
-    UString toString(ExecState *exec) const;
-    JSObject *toObject(ExecState *exec) const;
-  };
-
-  class BooleanImp : public JSCell {
-  public:
-    BooleanImp(bool v = false) : val(v) { }
-    bool value() const { return val; }
-
-    Type type() const { return BooleanType; }
-
-    JSValue *toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
-    bool toBoolean(ExecState *exec) const;
-    double toNumber(ExecState *exec) const;
-    UString toString(ExecState *exec) const;
-    JSObject *toObject(ExecState *exec) const;
-
-  private:
-    bool val;
-  };
-  
   class StringImp : public JSCell {
   public:
     StringImp(const UString& v) : val(v) { }
     UString value() const { return val; }
 
-    Type type() const { return StringType; }
+    JSType type() const { return StringType; }
 
-    JSValue *toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
+    JSValue *toPrimitive(ExecState *exec, JSType preferred = UnspecifiedType) const;
     bool toBoolean(ExecState *exec) const;
     double toNumber(ExecState *exec) const;
     UString toString(ExecState *exec) const;
@@ -108,13 +71,13 @@ namespace KJS {
   class NumberImp : public JSCell {
     friend class ConstantValues;
     friend class InterpreterImp;
-    friend JSValue *jsNumber(double);
+    friend JSValue *jsNumberCell(double);
   public:
     double value() const { return val; }
 
-    Type type() const { return NumberType; }
+    JSType type() const { return NumberType; }
 
-    JSValue *toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
+    JSValue *toPrimitive(ExecState *exec, JSType preferred = UnspecifiedType) const;
     bool toBoolean(ExecState *exec) const;
     double toNumber(ExecState *exec) const;
     UString toString(ExecState *exec) const;
index 1698319d25cb87869bfb4f46bce36c0f3ed7ae42..1d9bfa51ec9bf317bb6f3abb40cb410cec3d894a 100644 (file)
@@ -130,7 +130,7 @@ void JSObject::mark()
   _scope.mark();
 }
 
-Type JSObject::type() const
+JSType JSObject::type() const
 {
   return ObjectType;
 }
@@ -334,19 +334,17 @@ static ALWAYS_INLINE JSValue *tryGetAndCallProperty(ExecState *exec, const JSObj
     if (o->implementsCall()) { // spec says "not primitive type" but ...
       JSObject *thisObj = const_cast<JSObject*>(object);
       JSValue *def = o->call(exec, thisObj, List::empty());
-      Type defType = def->type();
-      if (defType == UnspecifiedType || defType == UndefinedType ||
-          defType == NullType || defType == BooleanType ||
-          defType == StringType || defType == NumberType) {
+      JSType defType = def->type();
+      ASSERT(defType != GetterSetterType);
+      if (defType != ObjectType)
         return def;
-      }
     }
   }
   return NULL;
 }
 
 // ECMA 8.6.2.6
-JSValue *JSObject::defaultValue(ExecState *exec, Type hint) const
+JSValue *JSObject::defaultValue(ExecState *exec, JSType hint) const
 {
   Identifier firstPropertyName;
   Identifier secondPropertyName;
@@ -502,7 +500,7 @@ ReferenceList JSObject::propList(ExecState *exec, bool recursive)
   return list;
 }
 
-JSValue *JSObject::toPrimitive(ExecState *exec, Type preferredType) const
+JSValue *JSObject::toPrimitive(ExecState *exec, JSType preferredType) const
 {
   return defaultValue(exec,preferredType);
 }
index 705c6f0e8a992793293ad747bf7ea84470f60a50..06768bdb4ecdfd400ac961fee8b59ca629669ee9 100644 (file)
@@ -37,7 +37,9 @@
 #define KJS_MAX_STACK 1000
 #endif
 
+#include "JSType.h"
 #include "interpreter.h"
+#include "kxmlcore/AlwaysInline.h"
 #include "property_map.h"
 #include "property_slot.h"
 #include "scope_chain.h"
@@ -85,11 +87,11 @@ namespace KJS {
   // for a property.
   class GetterSetterImp : public JSCell {
   public:
-    Type type() const { return GetterSetterType; }
+    JSType type() const { return GetterSetterType; }
       
     GetterSetterImp() : getter(0), setter(0) { }
       
-    virtual JSValue *toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
+    virtual JSValue *toPrimitive(ExecState *exec, JSType preferred = UnspecifiedType) const;
     virtual bool toBoolean(ExecState *exec) const;
     virtual double toNumber(ExecState *exec) const;
     virtual UString toString(ExecState *exec) const;
@@ -123,7 +125,7 @@ namespace KJS {
     JSObject();
 
     virtual void mark();
-    virtual Type type() const;
+    virtual JSType type() const;
 
     /**
      * A pointer to a ClassInfo struct for this class. This provides a basic
@@ -326,7 +328,7 @@ namespace KJS {
      * Implementation of the [[DefaultValue]] internal property (implemented by
      * all Objects)
      */
-    virtual JSValue *defaultValue(ExecState *exec, Type hint) const;
+    virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
 
     /**
      * Whether or not the object implements the construct() method. If this
@@ -486,7 +488,7 @@ namespace KJS {
      */
     void setInternalValue(JSValue *v);
 
-    JSValue *toPrimitive(ExecState *exec, Type preferredType = UnspecifiedType) const;
+    JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
     bool toBoolean(ExecState *exec) const;
     double toNumber(ExecState *exec) const;
     UString toString(ExecState *exec) const;
@@ -622,7 +624,7 @@ inline bool JSCell::isObject(const ClassInfo *info) const
 // this method is here to be after the inline declaration of JSCell::isObject
 inline bool JSValue::isObject(const ClassInfo *c) const
 {
-    return !SimpleNumber::is(this) && downcast()->isObject(c);
+    return !JSImmediate::isImmediate(this) && downcast()->isObject(c);
 }
 
 // It may seem crazy to inline a function this large but it makes a big difference
index 2f140bb29b1238a57dadd3e02bb87637f55fc3a7..8a5645b9a6cd14f93b9f68d86fc8884a7e9cd08f 100644 (file)
  *
  */
 
+
+#include "JSType.h"
 #include "config.h"
 #include "operations.h"
 
-
-#include <stdio.h>
 #include <assert.h>
 #include <math.h>
+#include <stdio.h>
 #include <stdlib.h>
 
 #ifndef HAVE_FUNC_ISINF
@@ -107,8 +108,8 @@ bool isNegInf(double d)
 // ECMA 11.9.3
 bool equal(ExecState *exec, JSValue *v1, JSValue *v2)
 {
-    Type t1 = v1->type();
-    Type t2 = v2->type();
+    JSType t1 = v1->type();
+    JSType t2 = v2->type();
 
     if (t1 != t2) {
         if (t1 == UndefinedType)
@@ -161,8 +162,8 @@ bool equal(ExecState *exec, JSValue *v1, JSValue *v2)
 
 bool strictEqual(ExecState *exec, JSValue *v1, JSValue *v2)
 {
-  Type t1 = v1->type();
-  Type t2 = v2->type();
+  JSType t1 = v1->type();
+  JSType t2 = v2->type();
 
   if (t1 != t2)
     return false;
@@ -217,7 +218,7 @@ int minInt(int d1, int d2)
 JSValue *add(ExecState *exec, JSValue *v1, JSValue *v2, char oper)
 {
   // exception for the Date exception in defaultValue()
-  Type preferred = oper == '+' ? UnspecifiedType : NumberType;
+  JSType preferred = oper == '+' ? UnspecifiedType : NumberType;
   JSValue *p1 = v1->toPrimitive(exec, preferred);
   JSValue *p2 = v2->toPrimitive(exec, preferred);
 
index 365e3e560319907787f7feff69955e4bc39889d4..8ee7173672c6c46a493cfbae49d6101380b419c7 100644 (file)
  *
  */
 
+#include "JSType.h"
 #include "config.h"
-#include "reference.h"
-
 #include "internal.h"
+#include "reference.h"
 
 namespace KJS {
 
@@ -67,7 +67,7 @@ JSValue *Reference::getValue(ExecState *exec) const
 bool Reference::deleteValue(ExecState *exec)
 {
   JSValue *o = base;
-  Type t = o ? o->type() : NullType;
+  JSType t = o ? o->type() : NullType;
 
   // The spec doesn't mention what to do if the base is null... just return true
   if (t != ObjectType) {
diff --git a/JavaScriptCore/kjs/simple_number.h b/JavaScriptCore/kjs/simple_number.h
deleted file mode 100644 (file)
index d3b83fb..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  This file is part of the KDE libraries
- *  Copyright (C) 2003 Apple Computer, Inc
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KJS_SIMPLE_NUMBER_H
-#define KJS_SIMPLE_NUMBER_H
-
-#include <assert.h>
-#include <stdlib.h>
-#include "kxmlcore/AlwaysInline.h"
-
-namespace KJS {
-
-    class JSValue;
-
-    class SimpleNumber {
-    public:
-        static const unsigned long tag     = 1; // 01 is the full tag, since it's 2 bits long.
-        static const unsigned long tagMask = 3; // 11 is the tag mask, since it's 2 bits long.
-        
-        ALWAYS_INLINE
-        static JSValue *make(double d)
-        {
-            if (sizeof(float) == sizeof(unsigned long) &&
-                sizeof(double) == sizeof(unsigned long long) &&
-                sizeof(JSValue *) >= sizeof(unsigned long)) {
-                // 32-bit
-                union {
-                    unsigned long asBits;
-                    float         asFloat;
-                } floatUnion;
-                floatUnion.asFloat = d;
-                
-                if ((floatUnion.asBits & tagMask) != 0)
-                  return 0;
-                
-                // Check for loss in conversion to float
-                union {
-                    unsigned long long asBits;
-                    double             asDouble;
-                } doubleUnion1, doubleUnion2;
-                doubleUnion1.asDouble = floatUnion.asFloat;
-                doubleUnion2.asDouble = d;
-                if (doubleUnion1.asBits != doubleUnion2.asBits)
-                    return 0;
-                
-                return reinterpret_cast<JSValue *>(floatUnion.asBits | tag);
-            } else if (sizeof(double) == sizeof(unsigned long) &&
-                       sizeof(JSValue*) >= sizeof(unsigned long)) {
-                // 64-bit
-                union {
-                    unsigned long asBits;
-                    double        asDouble;
-                } doubleUnion;
-                doubleUnion.asDouble = d;
-                
-                if ((doubleUnion.asBits & tagMask) != 0)
-                    return 0;
-
-                return reinterpret_cast<JSValue *>(doubleUnion.asBits | tag);
-            } else {
-                // could just return 0 here, but nicer to be explicit about not supporting the platform well
-                abort();
-            }
-        }
-
-        static bool is(const JSValue *imp)
-        {
-            return (reinterpret_cast<unsigned long>(imp) & tagMask) == tag;
-        }
-        
-        ALWAYS_INLINE
-        static double value(const JSValue *imp)
-        {
-            assert(is(imp));
-            
-            if (sizeof(float) == sizeof(unsigned long)) {
-                // 32-bit
-                union {
-                    unsigned long asBits;
-                    float         asFloat;
-                } floatUnion;
-                floatUnion.asBits = reinterpret_cast<unsigned long>(imp) & ~tagMask;
-                return floatUnion.asFloat;
-            } else if (sizeof(double) == sizeof(unsigned long)) {
-                // 64-bit
-                union {
-                    unsigned long asBits;
-                    double        asDouble;
-                } doubleUnion;
-                doubleUnion.asBits = reinterpret_cast<unsigned long>(imp) & ~tagMask;
-                return doubleUnion.asDouble;
-            } else {
-                // could just return 0 here, but nicer to be explicit about not supporting the platform well
-                abort();
-            }
-        }
-        
-    };
-
-}
-
-#endif
index ab6823c0888812fb4740993854e92d180b4b4c2b..05627b4c152272769f7829d2551e80e5c4080bc5 100644 (file)
@@ -79,7 +79,7 @@ bool StringInstance::getOwnPropertySlot(ExecState *exec, const Identifier& prope
     if (index < length) {
     slot.setCustomIndex(this, index, indexGetter);
     return true;
-  }
+    }
   }
 
   return JSObject::getOwnPropertySlot(exec, propertyName, slot);
index 0ad3bab334b57f803657f487ba22f76f513e2e62..2ef9324d47f1f9854f942a4c71938e93d7f48042 100644 (file)
 
 namespace KJS {
 
-JSCell *ConstantValues::undefined = NULL;
-JSCell *ConstantValues::null = NULL;
-JSCell *ConstantValues::jsTrue = NULL;
-JSCell *ConstantValues::jsFalse = NULL;
-
 static const double D16 = 65536.0;
 static const double D32 = 4294967296.0;
 
@@ -122,17 +117,7 @@ uint16_t JSValue::toUInt16(ExecState *exec) const
 
 JSObject *JSValue::toObject(ExecState *exec) const
 {
-    if (SimpleNumber::is(this))
-        return static_cast<const NumberImp *>(this)->NumberImp::toObject(exec);
-    return downcast()->toObject(exec);
-}
-
-bool JSCell::getBoolean(bool &booleanValue) const
-{
-    if (!isBoolean())
-        return false;
-    booleanValue = static_cast<const BooleanImp *>(this)->value();
-    return true;
+    return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : downcast()->toObject(exec);
 }
 
 bool JSCell::getNumber(double &numericValue) const
@@ -181,37 +166,11 @@ JSCell *jsString(const UString &s)
     return s.isNull() ? new StringImp("") : new StringImp(s);
 }
 
-JSValue *jsNumber(double d)
+// This method includes a PIC branch to set up the NumberImp's vtable, so we quarantine
+// it in a separate function to keep the normal case speedy.
+JSValue *jsNumberCell(double d)
 {
-  JSValue *v = SimpleNumber::make(d);
-  return v ? v : new NumberImp(d);
+    return new NumberImp(d);
 }
 
-void ConstantValues::initIfNeeded()
-{
-    if (undefined)
-        return;
-    
-    undefined = new UndefinedImp();
-    null = new NullImp();
-    jsTrue = new BooleanImp(true);
-    jsFalse = new BooleanImp(false);
-}
-
-void ConstantValues::mark()
-{
-    if (JSCell *v = undefined)
-        if (!v->marked())
-            v->mark();
-    if (JSCell *v = null)
-        if (!v->marked())
-            v->mark();
-    if (JSCell *v = jsTrue)
-        if (!v->marked())
-            v->mark();
-    if (JSCell *v = jsFalse)
-        if (!v->marked())
-            v->mark();
-}
-
-}
+} // namespace KJS
\ No newline at end of file
index 198623fa989f0f09419adef58f1d3046f56a4885..3f5a6068b9b5457653f36c934a0c9dd9546b3fc8 100644 (file)
 
 #endif
 
-#include <assert.h>
-#include <stdlib.h> // for size_t
-#include "simple_number.h"
+#include "JSImmediate.h"
+#include "JSType.h"
+#include "kxmlcore/Assertions.h"
 #include "ustring.h"
 
+#include <stdlib.h> // for size_t
+
 namespace KJS {
 
 class ClassInfo;
 class ExecState;
 class JSObject;
 
-/**
- * Primitive types
- */
-enum Type {
-    UnspecifiedType   = 0,
-    UndefinedType     = 1,
-    NullType          = 2,
-    BooleanType       = 3,
-    StringType        = 4,
-    NumberType        = 5,
-    ObjectType        = 6,
-    GetterSetterType  = 7
-};
-
 /**
  * JSValue is the base type for all primitives (Undefined, Null, Boolean,
  * String, Number) and objects in ECMAScript.
@@ -76,7 +64,7 @@ private:
 
 public:
     // Querying the type.
-    Type type() const;
+    JSType type() const;
     bool isUndefined() const;
     bool isNull() const;
     bool isUndefinedOrNull() const;
@@ -88,6 +76,7 @@ public:
 
     // Extracting the value.
     bool getBoolean(bool&) const;
+    bool getBoolean() const; // false if not a boolean
     bool getNumber(double&) const;
     double getNumber() const; // NaN if not a number
     bool getString(UString&) const;
@@ -99,7 +88,7 @@ public:
     bool getUInt32(uint32_t&) const;
 
     // Basic conversions.
-    JSValue *toPrimitive(ExecState *exec, Type preferredType = UnspecifiedType) const;
+    JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
     bool toBoolean(ExecState *exec) const;
     double toNumber(ExecState *exec) const;
     UString toString(ExecState *exec) const;
@@ -127,9 +116,6 @@ private:
 
 class JSCell : public JSValue {
     friend class Collector;
-    friend class UndefinedImp;
-    friend class NullImp;
-    friend class BooleanImp;
     friend class NumberImp;
     friend class StringImp;
     friend class JSObject;
@@ -139,15 +125,13 @@ private:
     virtual ~JSCell();
 public:
     // Querying the type.
-    virtual Type type() const = 0;
-    bool isBoolean() const;
+    virtual JSType type() const = 0;
     bool isNumber() const;
     bool isString() const;
     bool isObject() const;
     bool isObject(const ClassInfo *) const;
 
     // Extracting the value.
-    bool getBoolean(bool&) const;
     bool getNumber(double&) const;
     double getNumber() const; // NaN if not a number
     bool getString(UString&) const;
@@ -159,7 +143,7 @@ public:
     virtual bool getUInt32(uint32_t&) const;
 
     // Basic conversions.
-    virtual JSValue *toPrimitive(ExecState *exec, Type preferredType = UnspecifiedType) const = 0;
+    virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0;
     virtual bool toBoolean(ExecState *exec) const = 0;
     virtual double toNumber(ExecState *exec) const = 0;
     virtual UString toString(ExecState *exec) const = 0;
@@ -174,49 +158,46 @@ private:
     bool m_marked;
 };
 
-JSCell *jsUndefined();
-JSCell *jsNull();
+JSValue *jsUndefined();
+JSValue *jsNull();
 
-JSCell *jsBoolean(bool);
+JSValue *jsBoolean(bool);
 
+JSValue *jsNumberCell(double);
 JSValue *jsNumber(double);
 JSValue *jsNaN();
 
 JSCell *jsString(const UString &); // returns empty string if passed null string
 JSCell *jsString(const char * = ""); // returns empty string if passed 0
 
-extern const double NaN;
-extern const double Inf;
+extern double NaN;
+extern double Inf;
 
-class ConstantValues {
-public:
-    static JSCell *undefined;
-    static JSCell *null;
-    static JSCell *jsFalse;
-    static JSCell *jsTrue;
 
-    static void initIfNeeded();
-    static void mark();
-};
+inline JSValue *jsUndefined()
+{
+    return JSImmediate::undefinedImmediate();
+}
 
-inline JSCell *jsUndefined()
+inline JSValue *jsNull()
 {
-    return ConstantValues::undefined;
+    return JSImmediate::nullImmediate();
 }
 
-inline JSCell *jsNull()
+inline JSValue *jsNaN()
 {
-    return ConstantValues::null;
+    return JSImmediate::NaNImmediate();
 }
 
-inline JSCell *jsBoolean(bool b)
+inline JSValue *jsBoolean(bool b)
 {
-    return b ? ConstantValues::jsTrue : ConstantValues::jsFalse;
+    return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
 }
 
-inline JSValue *jsNaN()
+inline JSValue *jsNumber(double d)
 {
-    return SimpleNumber::make(NaN);
+    JSValue *v = JSImmediate::fromDouble(d);
+    return v ? v : jsNumberCell(d);
 }
 
 inline JSValue::JSValue()
@@ -236,11 +217,6 @@ inline JSCell::~JSCell()
 {
 }
 
-inline bool JSCell::isBoolean() const
-{
-    return type() == BooleanType;
-}
-
 inline bool JSCell::isNumber() const
 {
     return type() == NumberType;
@@ -268,13 +244,13 @@ inline void JSCell::mark()
 
 inline JSCell *JSValue::downcast()
 {
-    assert(!SimpleNumber::is(this));
+    ASSERT(!JSImmediate::isImmediate(this));
     return static_cast<JSCell *>(this);
 }
 
 inline const JSCell *JSValue::downcast() const
 {
-    assert(!SimpleNumber::is(this));
+    ASSERT(!JSImmediate::isImmediate(this));
     return static_cast<const JSCell *>(this);
 }
 
@@ -290,38 +266,48 @@ inline bool JSValue::isNull() const
 
 inline bool JSValue::isUndefinedOrNull() const
 {
-    return this == jsUndefined() || this == jsNull();
+    return JSImmediate::isUndefinedOrNull(this);
 }
 
 inline bool JSValue::isBoolean() const
 {
-    return !SimpleNumber::is(this) && downcast()->isBoolean();
+    return JSImmediate::isBoolean(this);
 }
 
 inline bool JSValue::isNumber() const
 {
-    return SimpleNumber::is(this) || downcast()->isNumber();
+    return JSImmediate::isNumber(this) || !JSImmediate::isImmediate(this) && downcast()->isNumber();
 }
 
 inline bool JSValue::isString() const
 {
-    return !SimpleNumber::is(this) && downcast()->isString();
+    return !JSImmediate::isImmediate(this) && downcast()->isString();
 }
 
 inline bool JSValue::isObject() const
 {
-    return !SimpleNumber::is(this) && downcast()->isObject();
+    return !JSImmediate::isImmediate(this) && downcast()->isObject();
 }
 
 inline bool JSValue::getBoolean(bool& v) const
 {
-    return !SimpleNumber::is(this) && downcast()->getBoolean(v);
+    if (JSImmediate::isBoolean(this)) {
+        v = JSImmediate::toBoolean(this);
+        return true;
+    }
+    
+    return false;
+}
+
+inline bool JSValue::getBoolean() const
+{
+    return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
 }
 
 inline bool JSValue::getNumber(double& v) const
 {
-    if (SimpleNumber::is(this)) {
-        v = SimpleNumber::value(this);
+    if (JSImmediate::isImmediate(this)) {
+        v = JSImmediate::toDouble(this);
         return true;
     }
     return downcast()->getNumber(v);
@@ -329,33 +315,33 @@ inline bool JSValue::getNumber(double& v) const
 
 inline double JSValue::getNumber() const
 {
-    return SimpleNumber::is(this) ? SimpleNumber::value(this) : downcast()->getNumber();
+    return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : downcast()->getNumber();
 }
 
 inline bool JSValue::getString(UString& s) const
 {
-    return !SimpleNumber::is(this) && downcast()->getString(s);
+    return !JSImmediate::isImmediate(this) && downcast()->getString(s);
 }
 
 inline UString JSValue::getString() const
 {
-    return SimpleNumber::is(this) ? UString() : downcast()->getString();
+    return JSImmediate::isImmediate(this) ? UString() : downcast()->getString();
 }
 
 inline JSObject *JSValue::getObject()
 {
-    return SimpleNumber::is(this) ? 0 : downcast()->getObject();
+    return JSImmediate::isImmediate(this) ? 0 : downcast()->getObject();
 }
 
 inline const JSObject *JSValue::getObject() const
 {
-    return SimpleNumber::is(this) ? 0 : downcast()->getObject();
+    return JSImmediate::isImmediate(this) ? 0 : downcast()->getObject();
 }
 
 inline bool JSValue::getUInt32(uint32_t& v) const
 {
-    if (SimpleNumber::is(this)) {
-        double d = SimpleNumber::value(this);
+    if (JSImmediate::isImmediate(this)) {
+        double d = JSImmediate::toDouble(this);
         if (!(d >= 0) || d > 0xFFFFFFFFUL) // true for NaN
             return false;
         v = static_cast<uint32_t>(d);
@@ -366,50 +352,38 @@ inline bool JSValue::getUInt32(uint32_t& v) const
 
 inline void JSValue::mark()
 {
-    if (!SimpleNumber::is(this))
-        downcast()->mark();
+    ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
+    downcast()->mark();
 }
 
 inline bool JSValue::marked() const
 {
-    return SimpleNumber::is(this) || downcast()->marked();
+    return JSImmediate::isImmediate(this) || downcast()->marked();
 }
 
-inline Type JSValue::type() const
+inline JSType JSValue::type() const
 {
-    return SimpleNumber::is(this) ? NumberType : downcast()->type();
+    return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : downcast()->type();
 }
 
-inline JSValue *JSValue::toPrimitive(ExecState *exec, Type preferredType) const
+inline JSValue *JSValue::toPrimitive(ExecState *exec, JSType preferredType) const
 {
-    return SimpleNumber::is(this) ? const_cast<JSValue *>(this) : downcast()->toPrimitive(exec, preferredType);
+    return JSImmediate::isImmediate(this) ? const_cast<JSValue *>(this) : downcast()->toPrimitive(exec, preferredType);
 }
 
 inline bool JSValue::toBoolean(ExecState *exec) const
 {
-    if (SimpleNumber::is(this)) {
-        double d = SimpleNumber::value(this);
-        return d < 0 || d > 0; // false for NaN
-    }
-
-    return downcast()->toBoolean(exec);
+    return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : downcast()->toBoolean(exec);
 }
 
 inline double JSValue::toNumber(ExecState *exec) const
 {
-    return SimpleNumber::is(this) ? SimpleNumber::value(this) : downcast()->toNumber(exec);
+    return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : downcast()->toNumber(exec);
 }
 
 inline UString JSValue::toString(ExecState *exec) const
 {
-    if (SimpleNumber::is(this)) {
-        double d = SimpleNumber::value(this);
-        if (d == 0.0) // +0.0 or -0.0
-            d = 0.0;
-        return UString::from(d);
-    }
-
-    return downcast()->toString(exec);
+    return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : downcast()->toString(exec);
 }
 
 } // namespace