DFG string conversions and allocations should be inlined
https://bugs.webkit.org/show_bug.cgi?id=112376

Source/JavaScriptCore: 

Reviewed by Geoffrey Garen.
        
This turns new String(), String(), String.prototype.valueOf(), and
String.prototype.toString() into intrinsics. It gives the DFG the ability to handle
conversions from StringObject to JSString and vice-versa, and also gives it the
ability to handle cases where a variable may be either a StringObject or a JSString.
To do this, I added StringObject to value profiling (and removed the stale
distinction between Myarguments and Foreignarguments). I also cleaned up ToPrimitive
handling, using some of the new functionality but also taking advantage of the
existence of Identity(String:@a).
        
This is a 2% SunSpider speed-up. Also there are some speed-ups on V8v7 and Kraken.
On microbenchmarks that stress new String() this is a 14x speed-up.

* CMakeLists.txt:
* DerivedSources.make:
* DerivedSources.pri:
* GNUmakefile.list.am:
* bytecode/CodeBlock.h:
(CodeBlock):
(JSC::CodeBlock::hasExitSite):
(JSC):
* bytecode/DFGExitProfile.cpp:
(JSC::DFG::ExitProfile::hasExitSite):
(DFG):
* bytecode/DFGExitProfile.h:
(ExitProfile):
(JSC::DFG::ExitProfile::hasExitSite):
* bytecode/ExitKind.cpp:
(JSC::exitKindToString):
* bytecode/ExitKind.h:
* bytecode/SpeculatedType.cpp:
(JSC::dumpSpeculation):
(JSC::speculationToAbbreviatedString):
(JSC::speculationFromClassInfo):
* bytecode/SpeculatedType.h:
(JSC):
(JSC::isStringObjectSpeculation):
(JSC::isStringOrStringObjectSpeculation):
* create_hash_table:
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::executeEffects):
* dfg/DFGAbstractState.h:
(JSC::DFG::AbstractState::filterEdgeByUse):
* dfg/DFGByteCodeParser.cpp:
(ByteCodeParser):
(JSC::DFG::ByteCodeParser::handleCall):
(JSC::DFG::ByteCodeParser::emitArgumentPhantoms):
(DFG):
(JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::putStructureStoreElimination):
* dfg/DFGEdge.h:
(JSC::DFG::Edge::shift):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::isStringPrototypeMethodSane):
(FixupPhase):
(JSC::DFG::FixupPhase::canOptimizeStringObjectAccess):
(JSC::DFG::FixupPhase::observeUseKindOnNode):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::hasGlobalExitSite):
(Graph):
(JSC::DFG::Graph::hasExitSite):
(JSC::DFG::Graph::clobbersWorld):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToToString):
(Node):
(JSC::DFG::Node::hasStructure):
(JSC::DFG::Node::shouldSpeculateStringObject):
(JSC::DFG::Node::shouldSpeculateStringOrStringObject):
* dfg/DFGNodeType.h:
(DFG):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileToStringOnCell):
(DFG):
(JSC::DFG::SpeculativeJIT::compileNewStringObject):
(JSC::DFG::SpeculativeJIT::speculateObject):
(JSC::DFG::SpeculativeJIT::speculateObjectOrOther):
(JSC::DFG::SpeculativeJIT::speculateString):
(JSC::DFG::SpeculativeJIT::speculateStringObject):
(JSC::DFG::SpeculativeJIT::speculateStringOrStringObject):
(JSC::DFG::SpeculativeJIT::speculate):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
(SpeculativeJIT):
(JSC::DFG::SpeculateCellOperand::SpeculateCellOperand):
(DFG):
(JSC::DFG::SpeculativeJIT::speculateStringObjectForStructure):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGUseKind.cpp:
(WTF::printInternal):
* dfg/DFGUseKind.h:
(JSC::DFG::typeFilterFor):
* interpreter/CallFrame.h:
(JSC::ExecState::regExpPrototypeTable):
* runtime/CommonIdentifiers.h:
* runtime/Intrinsic.h:
* runtime/JSDestructibleObject.h:
(JSDestructibleObject):
(JSC::JSDestructibleObject::classInfoOffset):
* runtime/JSGlobalData.cpp:
(JSC):
(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::~JSGlobalData):
* runtime/JSGlobalData.h:
(JSGlobalData):
* runtime/JSObject.cpp:
* runtime/JSObject.h:
(JSC):
* runtime/JSWrapperObject.h:
(JSC::JSWrapperObject::allocationSize):
(JSWrapperObject):
(JSC::JSWrapperObject::internalValueOffset):
(JSC::JSWrapperObject::internalValueCellOffset):
* runtime/StringPrototype.cpp:
(JSC):
(JSC::StringPrototype::finishCreation):
(JSC::StringPrototype::create):
* runtime/StringPrototype.h:
(StringPrototype):

LayoutTests: 

Reviewed by Geoffrey Garen.

* fast/js/dfg-to-string-bad-toString-expected.txt: Added.
* fast/js/dfg-to-string-bad-toString.html: Added.
* fast/js/dfg-to-string-bad-valueOf-expected.txt: Added.
* fast/js/dfg-to-string-bad-valueOf.html: Added.
* fast/js/dfg-to-string-int-expected.txt: Added.
* fast/js/dfg-to-string-int-or-string-expected.txt: Added.
* fast/js/dfg-to-string-int-or-string.html: Added.
* fast/js/dfg-to-string-int.html: Added.
* fast/js/dfg-to-string-side-effect-clobbers-toString-expected.txt: Added.
* fast/js/dfg-to-string-side-effect-clobbers-toString.html: Added.
* fast/js/dfg-to-string-side-effect-expected.txt: Added.
* fast/js/dfg-to-string-side-effect.html: Added.
* fast/js/dfg-to-string-toString-becomes-bad-expected.txt: Added.
* fast/js/dfg-to-string-toString-becomes-bad-with-dictionary-string-prototype-expected.txt: Added.
* fast/js/dfg-to-string-toString-becomes-bad-with-dictionary-string-prototype.html: Added.
* fast/js/dfg-to-string-toString-becomes-bad.html: Added.
* fast/js/dfg-to-string-toString-in-string-expected.txt: Added.
* fast/js/dfg-to-string-toString-in-string.html: Added.
* fast/js/dfg-to-string-valueOf-becomes-bad-expected.txt: Added.
* fast/js/dfg-to-string-valueOf-becomes-bad.html: Added.
* fast/js/dfg-to-string-valueOf-in-string-expected.txt: Added.
* fast/js/dfg-to-string-valueOf-in-string.html: Added.
* fast/js/jsc-test-list:
* fast/js/regress/script-tests/string-concat-object.js: Added.
(foo):
* fast/js/regress/script-tests/string-concat-pair-object.js: Added.
(foo):
* fast/js/regress/script-tests/string-concat-pair-simple.js: Added.
(foo):
* fast/js/regress/script-tests/string-concat-simple.js: Added.
(foo):
* fast/js/regress/script-tests/string-cons-repeat.js: Added.
(foo):
* fast/js/regress/script-tests/string-cons-tower.js: Added.
(foo):
* fast/js/regress/string-concat-object-expected.txt: Added.
* fast/js/regress/string-concat-object.html: Added.
* fast/js/regress/string-concat-pair-object-expected.txt: Added.
* fast/js/regress/string-concat-pair-object.html: Added.
* fast/js/regress/string-concat-pair-simple-expected.txt: Added.
* fast/js/regress/string-concat-pair-simple.html: Added.
* fast/js/regress/string-concat-simple-expected.txt: Added.
* fast/js/regress/string-concat-simple.html: Added.
* fast/js/regress/string-cons-repeat-expected.txt: Added.
* fast/js/regress/string-cons-repeat.html: Added.
* fast/js/regress/string-cons-tower-expected.txt: Added.
* fast/js/regress/string-cons-tower.html: Added.
* fast/js/script-tests/dfg-to-string-bad-toString.js: Added.
(String.prototype.toString):
(foo):
* fast/js/script-tests/dfg-to-string-bad-valueOf.js: Added.
(String.prototype.valueOf):
(foo):
* fast/js/script-tests/dfg-to-string-int-or-string.js: Added.
(foo):
* fast/js/script-tests/dfg-to-string-int.js: Added.
(foo):
* fast/js/script-tests/dfg-to-string-side-effect-clobbers-toString.js: Added.
(foo):
* fast/js/script-tests/dfg-to-string-side-effect.js: Added.
(foo):
* fast/js/script-tests/dfg-to-string-toString-becomes-bad-with-dictionary-string-prototype.js: Added.
(foo):
(.String.prototype.toString):
* fast/js/script-tests/dfg-to-string-toString-becomes-bad.js: Added.
(foo):
(.String.prototype.toString):
* fast/js/script-tests/dfg-to-string-toString-in-string.js: Added.
(foo):
(.argument.toString):
* fast/js/script-tests/dfg-to-string-valueOf-becomes-bad.js: Added.
(foo):
(.String.prototype.valueOf):
* fast/js/script-tests/dfg-to-string-valueOf-in-string.js: Added.
(foo):
(.argument.valueOf):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@146089 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index 8b3b66f..7805d66 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -333,7 +333,6 @@
     runtime/RegExpObject.cpp
     runtime/RegExpPrototype.cpp
     runtime/StringConstructor.cpp
-    runtime/StringPrototype.cpp
 )
 
 set(JavaScriptCore_LIBRARIES
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 5040431..da3702b 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,139 @@
+2013-03-15  Filip Pizlo  <fpizlo@apple.com>
+
+        DFG string conversions and allocations should be inlined
+        https://bugs.webkit.org/show_bug.cgi?id=112376
+
+        Reviewed by Geoffrey Garen.
+        
+        This turns new String(), String(), String.prototype.valueOf(), and
+        String.prototype.toString() into intrinsics. It gives the DFG the ability to handle
+        conversions from StringObject to JSString and vice-versa, and also gives it the
+        ability to handle cases where a variable may be either a StringObject or a JSString.
+        To do this, I added StringObject to value profiling (and removed the stale
+        distinction between Myarguments and Foreignarguments). I also cleaned up ToPrimitive
+        handling, using some of the new functionality but also taking advantage of the
+        existence of Identity(String:@a).
+        
+        This is a 2% SunSpider speed-up. Also there are some speed-ups on V8v7 and Kraken.
+        On microbenchmarks that stress new String() this is a 14x speed-up.
+
+        * CMakeLists.txt:
+        * DerivedSources.make:
+        * DerivedSources.pri:
+        * GNUmakefile.list.am:
+        * bytecode/CodeBlock.h:
+        (CodeBlock):
+        (JSC::CodeBlock::hasExitSite):
+        (JSC):
+        * bytecode/DFGExitProfile.cpp:
+        (JSC::DFG::ExitProfile::hasExitSite):
+        (DFG):
+        * bytecode/DFGExitProfile.h:
+        (ExitProfile):
+        (JSC::DFG::ExitProfile::hasExitSite):
+        * bytecode/ExitKind.cpp:
+        (JSC::exitKindToString):
+        * bytecode/ExitKind.h:
+        * bytecode/SpeculatedType.cpp:
+        (JSC::dumpSpeculation):
+        (JSC::speculationToAbbreviatedString):
+        (JSC::speculationFromClassInfo):
+        * bytecode/SpeculatedType.h:
+        (JSC):
+        (JSC::isStringObjectSpeculation):
+        (JSC::isStringOrStringObjectSpeculation):
+        * create_hash_table:
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::executeEffects):
+        * dfg/DFGAbstractState.h:
+        (JSC::DFG::AbstractState::filterEdgeByUse):
+        * dfg/DFGByteCodeParser.cpp:
+        (ByteCodeParser):
+        (JSC::DFG::ByteCodeParser::handleCall):
+        (JSC::DFG::ByteCodeParser::emitArgumentPhantoms):
+        (DFG):
+        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::putStructureStoreElimination):
+        * dfg/DFGEdge.h:
+        (JSC::DFG::Edge::shift):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::isStringPrototypeMethodSane):
+        (FixupPhase):
+        (JSC::DFG::FixupPhase::canOptimizeStringObjectAccess):
+        (JSC::DFG::FixupPhase::observeUseKindOnNode):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::hasGlobalExitSite):
+        (Graph):
+        (JSC::DFG::Graph::hasExitSite):
+        (JSC::DFG::Graph::clobbersWorld):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToToString):
+        (Node):
+        (JSC::DFG::Node::hasStructure):
+        (JSC::DFG::Node::shouldSpeculateStringObject):
+        (JSC::DFG::Node::shouldSpeculateStringOrStringObject):
+        * dfg/DFGNodeType.h:
+        (DFG):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileToStringOnCell):
+        (DFG):
+        (JSC::DFG::SpeculativeJIT::compileNewStringObject):
+        (JSC::DFG::SpeculativeJIT::speculateObject):
+        (JSC::DFG::SpeculativeJIT::speculateObjectOrOther):
+        (JSC::DFG::SpeculativeJIT::speculateString):
+        (JSC::DFG::SpeculativeJIT::speculateStringObject):
+        (JSC::DFG::SpeculativeJIT::speculateStringOrStringObject):
+        (JSC::DFG::SpeculativeJIT::speculate):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        (SpeculativeJIT):
+        (JSC::DFG::SpeculateCellOperand::SpeculateCellOperand):
+        (DFG):
+        (JSC::DFG::SpeculativeJIT::speculateStringObjectForStructure):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGUseKind.cpp:
+        (WTF::printInternal):
+        * dfg/DFGUseKind.h:
+        (JSC::DFG::typeFilterFor):
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::regExpPrototypeTable):
+        * runtime/CommonIdentifiers.h:
+        * runtime/Intrinsic.h:
+        * runtime/JSDestructibleObject.h:
+        (JSDestructibleObject):
+        (JSC::JSDestructibleObject::classInfoOffset):
+        * runtime/JSGlobalData.cpp:
+        (JSC):
+        (JSC::JSGlobalData::JSGlobalData):
+        (JSC::JSGlobalData::~JSGlobalData):
+        * runtime/JSGlobalData.h:
+        (JSGlobalData):
+        * runtime/JSObject.cpp:
+        * runtime/JSObject.h:
+        (JSC):
+        * runtime/JSWrapperObject.h:
+        (JSC::JSWrapperObject::allocationSize):
+        (JSWrapperObject):
+        (JSC::JSWrapperObject::internalValueOffset):
+        (JSC::JSWrapperObject::internalValueCellOffset):
+        * runtime/StringPrototype.cpp:
+        (JSC):
+        (JSC::StringPrototype::finishCreation):
+        (JSC::StringPrototype::create):
+        * runtime/StringPrototype.h:
+        (StringPrototype):
+
 2013-03-18  Filip Pizlo  <fpizlo@apple.com>
 
         ObjectPrototype properties should be eagerly created rather than lazily via static tables
diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make
index 55a76e2..517063d 100644
--- a/Source/JavaScriptCore/DerivedSources.make
+++ b/Source/JavaScriptCore/DerivedSources.make
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
+# Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013 Apple Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -55,7 +55,6 @@
     RegExpJitTables.h \
     RegExpObject.lut.h \
     StringConstructor.lut.h \
-    StringPrototype.lut.h \
     docs/bytecode.html \
     udis86_itab.h \
 #
diff --git a/Source/JavaScriptCore/DerivedSources.pri b/Source/JavaScriptCore/DerivedSources.pri
index d637569..c27c15f 100644
--- a/Source/JavaScriptCore/DerivedSources.pri
+++ b/Source/JavaScriptCore/DerivedSources.pri
@@ -24,7 +24,6 @@
     runtime/RegExpObject.cpp \
     runtime/RegExpPrototype.cpp \
     runtime/StringConstructor.cpp \
-    runtime/StringPrototype.cpp \
 
 KEYWORDLUT_FILES += \
     parser/Keywords.table
diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am
index f418387..14117fc 100644
--- a/Source/JavaScriptCore/GNUmakefile.list.am
+++ b/Source/JavaScriptCore/GNUmakefile.list.am
@@ -28,7 +28,6 @@
 	DerivedSources/JavaScriptCore/RegExpObject.lut.h \
 	DerivedSources/JavaScriptCore/RegExpPrototype.lut.h \
 	DerivedSources/JavaScriptCore/StringConstructor.lut.h \
-	DerivedSources/JavaScriptCore/StringPrototype.lut.h \
 	DerivedSources/JavaScriptCore/LLIntDesiredOffsets.h \
 	DerivedSources/JavaScriptCore/LLIntAssembly.h
 
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index f5f5312..1c7c58a 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -787,6 +787,8 @@
             ASSERT(JITCode::isBaselineCode(getJITType()));
             return m_exitProfile.add(site);
         }
+        
+        bool hasExitSite(const DFG::FrequentExitSite& site) const { return m_exitProfile.hasExitSite(site); }
 
         DFG::ExitProfile& exitProfile() { return m_exitProfile; }
         
@@ -1389,7 +1391,7 @@
             return baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame);
         return baselineCodeBlock;
     }
-    
+
     inline int CodeBlock::argumentIndexAfterCapture(size_t argument)
     {
         if (argument >= static_cast<size_t>(symbolTable()->parameterCount()))
diff --git a/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp b/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp
index 9f7e901..d36878f 100644
--- a/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp
+++ b/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp
@@ -70,6 +70,18 @@
     return result;
 }
 
+bool ExitProfile::hasExitSite(const FrequentExitSite& site) const
+{
+    if (!m_frequentExitSites)
+        return false;
+    
+    for (unsigned i = m_frequentExitSites->size(); i--;) {
+        if (m_frequentExitSites->at(i) == site)
+            return true;
+    }
+    return false;
+}
+
 QueryableExitProfile::QueryableExitProfile(const ExitProfile& profile)
 {
     if (!profile.m_frequentExitSites)
diff --git a/Source/JavaScriptCore/bytecode/DFGExitProfile.h b/Source/JavaScriptCore/bytecode/DFGExitProfile.h
index 61466f4..fe7b2f9 100644
--- a/Source/JavaScriptCore/bytecode/DFGExitProfile.h
+++ b/Source/JavaScriptCore/bytecode/DFGExitProfile.h
@@ -133,6 +133,20 @@
     // meant to only be used from debugging/profiling code.
     Vector<FrequentExitSite> exitSitesFor(unsigned bytecodeIndex);
     
+    // This is O(n) and should be called on less-frequently executed code paths
+    // in the compiler. It should be strictly cheaper than building a
+    // QueryableExitProfile, if you really expect this to be called infrequently
+    // and you believe that there are few exit sites.
+    bool hasExitSite(const FrequentExitSite&) const;
+    bool hasExitSite(ExitKind kind) const
+    {
+        return hasExitSite(FrequentExitSite(kind));
+    }
+    bool hasExitSite(unsigned bytecodeIndex, ExitKind kind) const
+    {
+        return hasExitSite(FrequentExitSite(bytecodeIndex, kind));
+    }
+    
 private:
     friend class QueryableExitProfile;
     
diff --git a/Source/JavaScriptCore/bytecode/ExitKind.cpp b/Source/JavaScriptCore/bytecode/ExitKind.cpp
index faa6348..a8d9045 100644
--- a/Source/JavaScriptCore/bytecode/ExitKind.cpp
+++ b/Source/JavaScriptCore/bytecode/ExitKind.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,6 +64,8 @@
         return "InadequateCoverage";
     case ArgumentsEscaped:
         return "ArgumentsEscaped";
+    case NotStringObject:
+        return "NotStringObject";
     case Uncountable:
         return "Uncountable";
     case UncountableWatchpoint:
diff --git a/Source/JavaScriptCore/bytecode/ExitKind.h b/Source/JavaScriptCore/bytecode/ExitKind.h
index f28995f0..8b34f4e 100644
--- a/Source/JavaScriptCore/bytecode/ExitKind.h
+++ b/Source/JavaScriptCore/bytecode/ExitKind.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -44,6 +44,7 @@
     StoreToHoleOrOutOfBounds, // We're simultaneously speculating that we're in bounds and not accessing a hole, and one of those things didn't pan out.
     InadequateCoverage, // We exited because we ended up in code that didn't have profiling coverage.
     ArgumentsEscaped, // We exited because arguments escaped but we didn't expect them to.
+    NotStringObject, // We exited because we shouldn't have attempted to optimize string object access.
     Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME.
     UncountableWatchpoint // We exited because of a watchpoint, which isn't counted because watchpoints do tracking themselves.
 };
diff --git a/Source/JavaScriptCore/bytecode/SpeculatedType.cpp b/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
index 7b78592..0e33b65 100644
--- a/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
+++ b/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,6 +33,7 @@
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "Operations.h"
+#include "StringObject.h"
 #include "ValueProfile.h"
 #include <wtf/BoundsCheckedPointer.h>
 #include <wtf/StringPrintStream.h>
@@ -120,13 +121,8 @@
     else
         isTop = false;
     
-    if (value & SpecMyArguments)
-        myOut.print("Myarguments");
-    else
-        isTop = false;
-    
-    if (value & SpecForeignArguments)
-        myOut.print("Foreignarguments");
+    if (value & SpecArguments)
+        myOut.print("Arguments");
     else
         isTop = false;
     
@@ -135,6 +131,11 @@
     else
         isTop = false;
     
+    if (value & SpecStringObject)
+        myOut.print("Stringobject");
+    else
+        isTop = false;
+    
     if (value & SpecInt32)
         myOut.print("Int");
     else
@@ -197,10 +198,12 @@
         return "<Float32array>";
     if (isFloat64ArraySpeculation(prediction))
         return "<Float64array>";
-    if (isMyArgumentsSpeculation(prediction))
-        return "<Myarguments>";
     if (isArgumentsSpeculation(prediction))
         return "<Arguments>";
+    if (isStringObjectSpeculation(prediction))
+        return "<StringObject>";
+    if (isStringOrStringObjectSpeculation(prediction))
+        return "<StringOrStringObject>";
     if (isObjectSpeculation(prediction))
         return "<Object>";
     if (isCellSpeculation(prediction))
@@ -232,11 +235,13 @@
         return SpecArray;
     
     if (classInfo == &Arguments::s_info)
-        return SpecArguments; // Cannot distinguish between MyArguments and ForeignArguments at this stage. That happens in the flow analysis.
+        return SpecArguments;
+    
+    if (classInfo == &StringObject::s_info)
+        return SpecStringObject;
     
     if (classInfo->isSubClassOf(&JSFunction::s_info))
         return SpecFunction;
-
     
     if (classInfo->typedArrayStorageType != TypedArrayNone) {
         switch (classInfo->typedArrayStorageType) {
diff --git a/Source/JavaScriptCore/bytecode/SpeculatedType.h b/Source/JavaScriptCore/bytecode/SpeculatedType.h
index 5854f5c..b50b7ce 100644
--- a/Source/JavaScriptCore/bytecode/SpeculatedType.h
+++ b/Source/JavaScriptCore/bytecode/SpeculatedType.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -49,9 +49,8 @@
 static const SpeculatedType SpecUint32Array       = 0x00000400; // It's definitely an Uint32Array or one of its subclasses.
 static const SpeculatedType SpecFloat32Array      = 0x00000800; // It's definitely an Uint16Array or one of its subclasses.
 static const SpeculatedType SpecFloat64Array      = 0x00001000; // It's definitely an Uint16Array or one of its subclasses.
-static const SpeculatedType SpecMyArguments       = 0x00002000; // It's definitely an Arguments object, and it's definitely the one for my current frame.
-static const SpeculatedType SpecForeignArguments  = 0x00004000; // It's definitely an Arguments object, and it's definitely not mine.
-static const SpeculatedType SpecArguments         = 0x00006000; // It's definitely an Arguments object.
+static const SpeculatedType SpecArguments         = 0x00002000; // It's definitely an Arguments object.
+static const SpeculatedType SpecStringObject      = 0x00004000; // It's definitely a StringObject.
 static const SpeculatedType SpecObjectOther       = 0x00008000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
 static const SpeculatedType SpecObject            = 0x0000ffff; // Bitmask used for testing for any kind of object prediction.
 static const SpeculatedType SpecString            = 0x00010000; // It's definitely a JSString.
@@ -214,9 +213,14 @@
     return !!(value & (SpecArray | SpecOther)) && !(value & ~(SpecArray | SpecOther));
 }
 
-inline bool isMyArgumentsSpeculation(SpeculatedType value)
+inline bool isStringObjectSpeculation(SpeculatedType value)
 {
-    return value == SpecMyArguments;
+    return value == SpecStringObject;
+}
+
+inline bool isStringOrStringObjectSpeculation(SpeculatedType value)
+{
+    return !!value && !(value & ~(SpecString | SpecStringObject));
 }
 
 inline bool isInt32Speculation(SpeculatedType value)
diff --git a/Source/JavaScriptCore/create_hash_table b/Source/JavaScriptCore/create_hash_table
index cb2809d..875018c 100755
--- a/Source/JavaScriptCore/create_hash_table
+++ b/Source/JavaScriptCore/create_hash_table
@@ -271,8 +271,6 @@
         }
 
         my $intrinsic = "NoIntrinsic";
-        $intrinsic = "CharCodeAtIntrinsic" if ($key eq "charCodeAt");
-        $intrinsic = "CharAtIntrinsic" if ($key eq "charAt");
         $intrinsic = "FromCharCodeIntrinsic" if ($key eq "fromCharCode");
         if ($name eq "mathTable") {
             $intrinsic = "MinIntrinsic" if ($key eq "min");
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index a9e718c..74358ac 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -33,6 +33,7 @@
 #include "GetByIdStatus.h"
 #include "Operations.h"
 #include "PutByIdStatus.h"
+#include "StringObject.h"
 
 namespace JSC { namespace DFG {
 
@@ -769,7 +770,7 @@
             RELEASE_ASSERT_NOT_REACHED();
             break;
         }
-        forNode(node).set(SpecString);
+        forNode(node).set(m_graph.m_globalData.stringStructure.get());
         break;
     }
             
@@ -857,7 +858,7 @@
         
     case StringCharAt:
         node->setCanExit(true);
-        forNode(node).set(SpecString);
+        forNode(node).set(m_graph.m_globalData.stringStructure.get());
         break;
             
     case GetByVal: {
@@ -876,7 +877,7 @@
             forNode(node).makeTop();
             break;
         case Array::String:
-            forNode(node).set(SpecString);
+            forNode(node).set(m_graph.m_globalData.stringStructure.get());
             break;
         case Array::Arguments:
             forNode(node).makeTop();
@@ -1031,11 +1032,8 @@
             break;
         }
         
-        if (node->child1().useKind() == Int32Use) {
-            forNode(node).set(SpecInt32);
-            break;
-        }
-
+        ASSERT(node->child1().useKind() == UntypedUse);
+        
         AbstractValue& source = forNode(node->child1());
         AbstractValue& destination = forNode(node);
         
@@ -1060,6 +1058,8 @@
         // ToPrimitive will currently forget string constants. But that's not a big
         // deal since we don't do any optimization on those currently.
         
+        clobberWorld(node->codeOrigin, indexInBlock);
+        
         SpeculatedType type = source.m_type;
         if (type & ~(SpecNumber | SpecString | SpecBoolean)) {
             type &= (SpecNumber | SpecString | SpecBoolean);
@@ -1068,9 +1068,38 @@
         destination.set(type);
         break;
     }
+        
+    case ToString: {
+        switch (node->child1().useKind()) {
+        case StringObjectUse:
+            // This also filters that the StringObject has the primordial StringObject
+            // structure.
+            forNode(node->child1()).filter(m_graph.globalObjectFor(node->codeOrigin)->stringObjectStructure());
+            node->setCanExit(true); // We could be more precise but it's likely not worth it.
+            break;
+        case StringOrStringObjectUse:
+            node->setCanExit(true); // We could be more precise but it's likely not worth it.
+            break;
+        case CellUse:
+        case UntypedUse:
+            clobberWorld(node->codeOrigin, indexInBlock);
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+        forNode(node).set(m_graph.m_globalData.stringStructure.get());
+        break;
+    }
+        
+    case NewStringObject: {
+        ASSERT(node->structure()->classInfo() == &StringObject::s_info);
+        forNode(node).set(node->structure());
+        break;
+    }
             
     case StrCat:
-        forNode(node).set(SpecString);
+        forNode(node).set(m_graph.m_globalData.stringStructure.get());
         break;
             
     case NewArray:
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h
index e6334e1..de1f17d 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h
@@ -190,6 +190,7 @@
         case KnownInt32Use:
         case KnownNumberUse:
         case KnownCellUse:
+        case KnownStringUse:
             ASSERT(!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())));
             break;
         default:
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index ab25c23..634d1055c 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -39,6 +39,7 @@
 #include "PreciseJumpTargets.h"
 #include "PutByIdStatus.h"
 #include "ResolveGlobalStatus.h"
+#include "StringConstructor.h"
 #include <wtf/CommaPrinter.h>
 #include <wtf/HashMap.h>
 #include <wtf/MathExtras.h>
@@ -164,6 +165,7 @@
     // Handle calls. This resolves issues surrounding inlining and intrinsics.
     void handleCall(Interpreter*, Instruction* currentInstruction, NodeType op, CodeSpecializationKind);
     void emitFunctionChecks(const CallLinkStatus&, Node* callTarget, int registerOffset, CodeSpecializationKind);
+    void emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind);
     // Handle inlining. Return true if it succeeded, false if we need to plant a call.
     bool handleInlining(bool usesResult, Node* callTargetNode, int resultOperand, const CallLinkStatus&, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind);
     // Handle setting the result of an intrinsic.
@@ -1206,9 +1208,14 @@
     }
 
     if (InternalFunction* function = callLinkStatus.internalFunction()) {
-        if (handleConstantInternalFunction(usesResult, resultOperand, function, registerOffset, argumentCountIncludingThis, prediction, kind))
+        if (handleConstantInternalFunction(usesResult, resultOperand, function, registerOffset, argumentCountIncludingThis, prediction, kind)) {
+            // This phantoming has to be *after* the code for the intrinsic, to signify that
+            // the inputs must be kept alive whatever exits the intrinsic may do.
+            addToGraph(Phantom, callTarget);
+            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, kind);
             return;
-            
+        }
+        
         // Can only handle this using the generic call handler.
         addCall(interpreter, currentInstruction, op);
         return;
@@ -1219,14 +1226,10 @@
         emitFunctionChecks(callLinkStatus, callTarget, registerOffset, kind);
             
         if (handleIntrinsic(usesResult, resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction)) {
-            // Need to keep all inputs alive for OSR, and need to ensure that we get
-            // backwards propagation of NodeUsedAsValue. Note that inlining doesn't
-            // need to do this because it already Flushes the arguments, which has a
-            // similar effect.
+            // This phantoming has to be *after* the code for the intrinsic, to signify that
+            // the inputs must be kept alive whatever exits the intrinsic may do.
             addToGraph(Phantom, callTarget);
-            for (int i = 0; i < argumentCountIncludingThis; ++i)
-                addToGraph(Phantom, get(registerOffset + argumentToOperand(i)));
-            
+            emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, kind);
             return;
         }
     } else if (handleInlining(usesResult, callTarget, resultOperand, callLinkStatus, registerOffset, argumentCountIncludingThis, nextOffset, kind))
@@ -1261,6 +1264,12 @@
     }
 }
 
+void ByteCodeParser::emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind kind)
+{
+    for (int i = kind == CodeForCall ? 0 : 1; i < argumentCountIncludingThis; ++i)
+        addToGraph(Phantom, get(registerOffset + argumentToOperand(i)));
+}
+
 bool ByteCodeParser::handleInlining(bool usesResult, Node* callTargetNode, int resultOperand, const CallLinkStatus& callLinkStatus, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind kind)
 {
     // First, the really simple checks: do we have an actual JS function?
@@ -1628,7 +1637,6 @@
     // is good enough.
     
     UNUSED_PARAM(prediction); // Remove this once we do more things.
-    UNUSED_PARAM(kind); // Remove this once we do more things.
     
     if (function->classInfo() == &ArrayConstructor::s_info) {
         if (argumentCountIncludingThis == 2) {
@@ -1644,6 +1652,19 @@
             usesResult, resultOperand,
             addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(0)));
         return true;
+    } else if (function->classInfo() == &StringConstructor::s_info) {
+        Node* result;
+        
+        if (argumentCountIncludingThis <= 1)
+            result = cellConstant(m_globalData->smallStrings.emptyString());
+        else
+            result = addToGraph(ToString, get(registerOffset + argumentToOperand(1)));
+        
+        if (kind == CodeForConstruct)
+            result = addToGraph(NewStringObject, OpInfo(function->globalObject()->stringObjectStructure()), result);
+        
+        setIntrinsicResult(usesResult, resultOperand, result);
+        return true;
     }
     
     return false;
diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
index 800ef51..2b23e19 100644
--- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
@@ -576,6 +576,8 @@
             case AllocatePropertyStorage:
             case ReallocatePropertyStorage:
             case TypeOf:
+            case ToString:
+            case NewStringObject:
                 return 0;
                 
             case GetIndexedPropertyStorage:
diff --git a/Source/JavaScriptCore/dfg/DFGEdge.h b/Source/JavaScriptCore/dfg/DFGEdge.h
index caa3b21..eb835b0 100644
--- a/Source/JavaScriptCore/dfg/DFGEdge.h
+++ b/Source/JavaScriptCore/dfg/DFGEdge.h
@@ -148,7 +148,7 @@
     friend class AdjacencyList;
     
 #if USE(JSVALUE64)
-    static uint32_t shift() { return 5; }
+    static uint32_t shift() { return 6; }
     
     static uintptr_t makeWord(Node* node, UseKind useKind, ProofStatus proofStatus)
     {
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 4b0bbf3..6e8d922 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -526,13 +526,69 @@
         }
             
         case ToPrimitive: {
-            if (node->child1()->shouldSpeculateInteger())
+            if (node->child1()->shouldSpeculateInteger()) {
                 setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
+                node->convertToIdentity();
+                break;
+            }
+            
+            if (node->child1()->shouldSpeculateString()) {
+                setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
+                node->convertToIdentity();
+                break;
+            }
+            
+            if (node->child1()->shouldSpeculateStringObject()
+                && canOptimizeStringObjectAccess(node->codeOrigin)) {
+                setUseKindAndUnboxIfProfitable<StringObjectUse>(node->child1());
+                node->convertToToString();
+                break;
+            }
+            
+            if (node->child1()->shouldSpeculateStringOrStringObject()
+                && canOptimizeStringObjectAccess(node->codeOrigin)) {
+                setUseKindAndUnboxIfProfitable<StringOrStringObjectUse>(node->child1());
+                node->convertToToString();
+                break;
+            }
+            
             // FIXME: Add string speculation here.
             // https://bugs.webkit.org/show_bug.cgi?id=110175
             break;
         }
             
+        case ToString: {
+            if (node->child1()->shouldSpeculateString()) {
+                setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
+                node->convertToIdentity();
+                break;
+            }
+            
+            if (node->child1()->shouldSpeculateStringObject()
+                && canOptimizeStringObjectAccess(node->codeOrigin)) {
+                setUseKindAndUnboxIfProfitable<StringObjectUse>(node->child1());
+                break;
+            }
+            
+            if (node->child1()->shouldSpeculateStringOrStringObject()
+                && canOptimizeStringObjectAccess(node->codeOrigin)) {
+                setUseKindAndUnboxIfProfitable<StringOrStringObjectUse>(node->child1());
+                break;
+            }
+            
+            if (node->child1()->shouldSpeculateCell()) {
+                setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
+                break;
+            }
+            
+            break;
+        }
+            
+        case NewStringObject: {
+            setUseKindAndUnboxIfProfitable<KnownStringUse>(node->child1());
+            break;
+        }
+            
         case NewArray: {
             for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
                 node->setIndexingType(
@@ -806,6 +862,58 @@
 #endif
     }
     
+    bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, const Identifier& ident)
+    {
+        unsigned attributesUnused;
+        JSCell* specificValue;
+        PropertyOffset offset = stringPrototypeStructure->get(
+            globalData(), ident, attributesUnused, specificValue);
+        if (!isValidOffset(offset))
+            return false;
+        
+        if (!specificValue)
+            return false;
+        
+        if (!specificValue->inherits(&JSFunction::s_info))
+            return false;
+        
+        JSFunction* function = jsCast<JSFunction*>(specificValue);
+        if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
+            return false;
+        
+        return true;
+    }
+    
+    bool canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
+    {
+        if (m_graph.hasExitSite(codeOrigin, NotStringObject))
+            return false;
+        
+        Structure* stringObjectStructure = m_graph.globalObjectFor(codeOrigin)->stringObjectStructure();
+        ASSERT(stringObjectStructure->storedPrototype().isObject());
+        ASSERT(stringObjectStructure->storedPrototype().asCell()->classInfo() == &StringPrototype::s_info);
+        
+        JSObject* stringPrototypeObject = asObject(stringObjectStructure->storedPrototype());
+        Structure* stringPrototypeStructure = stringPrototypeObject->structure();
+        if (stringPrototypeStructure->transitionWatchpointSetHasBeenInvalidated())
+            return false;
+        
+        if (stringPrototypeStructure->isDictionary())
+            return false;
+        
+        // We're being conservative here. We want DFG's ToString on StringObject to be
+        // used in both numeric contexts (that would call valueOf()) and string contexts
+        // (that would call toString()). We don't want the DFG to have to distinguish
+        // between the two, just because that seems like it would get confusing. So we
+        // just require both methods to be sane.
+        if (!isStringPrototypeMethodSane(stringPrototypeStructure, globalData().propertyNames->valueOf))
+            return false;
+        if (!isStringPrototypeMethodSane(stringPrototypeStructure, globalData().propertyNames->toString))
+            return false;
+        
+        return true;
+    }
+    
     void fixupSetLocalsInBlock(BasicBlock* block)
     {
         if (!block)
@@ -974,6 +1082,9 @@
         case CellUse:
         case ObjectUse:
         case StringUse:
+        case KnownStringUse:
+        case StringObjectUse:
+        case StringOrStringObjectUse:
             if (alwaysUnboxSimplePrimitives()
                 || isCellSpeculation(variable->prediction()))
                 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index 605a5a2..45bf669 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -376,6 +376,16 @@
         return baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, m_profiledBlock);
     }
     
+    bool hasGlobalExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
+    {
+        return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(exitKind));
+    }
+    
+    bool hasExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
+    {
+        return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(codeOrigin.bytecodeIndex, exitKind));
+    }
+    
     int argumentsRegisterFor(const CodeOrigin& codeOrigin)
     {
         if (!codeOrigin.inlineCallFrame)
@@ -522,6 +532,18 @@
         case PutByVal:
         case PutByValAlias:
             return !byValIsPure(node);
+        case ToString:
+            switch (node->child1().useKind()) {
+            case StringObjectUse:
+            case StringOrStringObjectUse:
+                return false;
+            case CellUse:
+            case UntypedUse:
+                return true;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+                return true;
+            }
         default:
             RELEASE_ASSERT_NOT_REACHED();
             return true; // If by some oddity we hit this case in release build it's safer to have CSE assume the worst.
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index 06e9915..505d7a2 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -349,6 +349,12 @@
         children.setChild1(Edge(phi));
     }
     
+    void convertToToString()
+    {
+        ASSERT(m_op == ToPrimitive);
+        m_op = ToString;
+    }
+    
     JSCell* weakConstant()
     {
         ASSERT(op() == WeakJSConstant);
@@ -844,6 +850,7 @@
         case ForwardStructureTransitionWatchpoint:
         case ArrayifyToStructure:
         case NewObject:
+        case NewStringObject:
             return true;
         default:
             return false;
@@ -1120,6 +1127,16 @@
         return isStringSpeculation(prediction());
     }
  
+    bool shouldSpeculateStringObject()
+    {
+        return isStringObjectSpeculation(prediction());
+    }
+    
+    bool shouldSpeculateStringOrStringObject()
+    {
+        return isStringOrStringObjectSpeculation(prediction());
+    }
+    
     bool shouldSpeculateFinalObject()
     {
         return isFinalObjectSpeculation(prediction());
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index afada5d..775928c 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -222,6 +222,8 @@
     macro(TypeOf, NodeResultJS) \
     macro(LogicalNot, NodeResultBoolean) \
     macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(ToString, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
+    macro(NewStringObject, NodeResultJS) \
     macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
     \
     /* Nodes used for activations. Activation support works by having it anchored at */\
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index 4ccb911..10bcc9b 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -1547,6 +1547,30 @@
     return string->value(exec).impl();
 }
 
+JSCell* DFG_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
+{
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+    
+    return StringObject::create(exec, structure, string);
+}
+
+JSCell* DFG_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
+{
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+    
+    return JSValue(cell).toString(exec);
+}
+
+JSCell* DFG_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
+{
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+
+    return JSValue::decode(value).toString(exec);
+}
+
 double DFG_OPERATION operationFModOnInts(int32_t a, int32_t b)
 {
     return fmod(a, b);
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h
index 99ed55a..9d57d55 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -85,6 +85,8 @@
 typedef JSCell* DFG_OPERATION (*C_DFGOperation_EC)(ExecState*, JSCell*);
 typedef JSCell* DFG_OPERATION (*C_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*);
 typedef JSCell* DFG_OPERATION (*C_DFGOperation_EIcf)(ExecState*, InlineCallFrame*);
+typedef JSCell* DFG_OPERATION (*C_DFGOperation_EJ)(ExecState*, EncodedJSValue);
+typedef JSCell* DFG_OPERATION (*C_DFGOperation_EJssSt)(ExecState*, JSString*, Structure*);
 typedef JSCell* DFG_OPERATION (*C_DFGOperation_EOZ)(ExecState*, JSObject*, int32_t);
 typedef JSCell* DFG_OPERATION (*C_DFGOperation_ESt)(ExecState*, Structure*);
 typedef double DFG_OPERATION (*D_DFGOperation_DD)(double, double);
@@ -212,6 +214,9 @@
 char* DFG_OPERATION operationRageEnsureContiguous(ExecState*, JSCell*);
 char* DFG_OPERATION operationEnsureArrayStorage(ExecState*, JSCell*);
 StringImpl* DFG_OPERATION operationResolveRope(ExecState*, JSString*);
+JSCell* DFG_OPERATION operationNewStringObject(ExecState*, JSString*, Structure*);
+JSCell* DFG_OPERATION operationToStringOnCell(ExecState*, JSCell*);
+JSCell* DFG_OPERATION operationToString(ExecState*, EncodedJSValue);
 
 // This method is used to lookup an exception hander, keyed by faultLocation, which is
 // the return location from one of the calls out to one of the helper operations above.
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index 815cbe2..8a4e0de 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -413,7 +413,8 @@
         }
         
         case StringCharAt:
-        case StrCat: {
+        case StrCat:
+        case ToString: {
             changed |= setPrediction(SpecString);
             break;
         }
@@ -439,6 +440,11 @@
             break;
         }
             
+        case NewStringObject: {
+            changed |= setPrediction(SpecStringObject);
+            break;
+        }
+            
         case CreateArguments: {
             changed |= setPrediction(SpecArguments);
             break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 345b275..4f83dad 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -3922,6 +3922,115 @@
     return temporary.gpr();
 }
 
+void SpeculativeJIT::compileToStringOnCell(Node* node)
+{
+    SpeculateCellOperand op1(this, node->child1());
+    GPRReg op1GPR = op1.gpr();
+    
+    switch (node->child1().useKind()) {
+    case StringObjectUse: {
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+        
+        if (!m_state.forNode(node->child1()).m_currentKnownStructure.isSubsetOf(StructureSet(m_jit.globalObjectFor(node->codeOrigin)->stringObjectStructure()))) {
+            speculateStringObject(op1GPR);
+            m_state.forNode(node->child1()).filter(SpecStringObject);
+        }
+        m_jit.loadPtr(JITCompiler::Address(op1GPR, JSWrapperObject::internalValueCellOffset()), resultGPR);
+        cellResult(resultGPR, node);
+        break;
+    }
+        
+    case StringOrStringObjectUse: {
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.loadPtr(JITCompiler::Address(op1GPR, JSCell::structureOffset()), resultGPR);
+        JITCompiler::Jump isString = m_jit.branchPtr(
+            JITCompiler::Equal, resultGPR, TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
+        
+        speculateStringObjectForStructure(resultGPR);
+        
+        m_jit.loadPtr(JITCompiler::Address(op1GPR, JSWrapperObject::internalValueCellOffset()), resultGPR);
+        
+        JITCompiler::Jump done = m_jit.jump();
+        isString.link(&m_jit);
+        m_jit.move(op1GPR, resultGPR);
+        done.link(&m_jit);
+        
+        m_state.forNode(node->child1()).filter(SpecString | SpecStringObject);
+        
+        cellResult(resultGPR, node);
+        break;
+    }
+        
+    case CellUse: {
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+        
+        // We flush registers instead of silent spill/fill because in this mode we
+        // believe that most likely the input is not a string, and we need to take
+        // slow path.
+        flushRegisters();
+        JITCompiler::Jump done;
+        if (node->child1()->prediction() & SpecString) {
+            done = m_jit.branchPtr(
+                JITCompiler::Equal,
+                JITCompiler::Address(op1GPR, JSCell::structureOffset()),
+                TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
+        }
+        callOperation(operationToStringOnCell, resultGPR, op1GPR);
+        if (done.isSet())
+            done.link(&m_jit);
+        cellResult(resultGPR, node);
+        break;
+    }
+        
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
+void SpeculativeJIT::compileNewStringObject(Node* node)
+{
+    SpeculateCellOperand operand(this, node->child1());
+    
+    GPRTemporary result(this);
+    GPRTemporary scratch1(this);
+    GPRTemporary scratch2(this);
+
+    GPRReg operandGPR = operand.gpr();
+    GPRReg resultGPR = result.gpr();
+    GPRReg scratch1GPR = scratch1.gpr();
+    GPRReg scratch2GPR = scratch2.gpr();
+    
+    JITCompiler::JumpList slowPath;
+    
+    emitAllocateJSObject<StringObject>(
+        resultGPR, TrustedImmPtr(node->structure()), TrustedImmPtr(0), scratch1GPR, scratch2GPR,
+        slowPath);
+    
+    m_jit.storePtr(
+        TrustedImmPtr(&StringObject::s_info),
+        JITCompiler::Address(resultGPR, JSDestructibleObject::classInfoOffset()));
+#if USE(JSVALUE64)
+    m_jit.store64(
+        operandGPR, JITCompiler::Address(resultGPR, JSWrapperObject::internalValueOffset()));
+#else
+    m_jit.store32(
+        TrustedImm32(JSValue::CellTag),
+        JITCompiler::Address(resultGPR, JSWrapperObject::internalValueOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+    m_jit.store32(
+        operandGPR,
+        JITCompiler::Address(resultGPR, JSWrapperObject::internalValueOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+#endif
+    
+    addSlowPathGenerator(slowPathCall(
+        slowPath, this, operationNewStringObject, resultGPR, operandGPR, node->structure()));
+    
+    cellResult(resultGPR, node);
+}
+
 void SpeculativeJIT::speculateInt32(Edge edge)
 {
     if (!needsTypeCheck(edge, SpecInt32))
@@ -3973,10 +4082,11 @@
         return;
     
     SpeculateCellOperand operand(this, edge);
+    GPRReg gpr = operand.gpr();
     DFG_TYPE_CHECK(
-        JSValueSource::unboxedCell(operand.gpr()), edge, SpecObject, m_jit.branchPtr(
+        JSValueSource::unboxedCell(gpr), edge, SpecObject, m_jit.branchPtr(
             MacroAssembler::Equal, 
-            MacroAssembler::Address(operand.gpr(), JSCell::structureOffset()), 
+            MacroAssembler::Address(gpr, JSCell::structureOffset()), 
             MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
 }
 
@@ -3993,7 +4103,7 @@
     MacroAssembler::Jump notCell = m_jit.branchTest64(
         MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister);
     DFG_TYPE_CHECK(
-        JSValueRegs(operand.gpr()), edge, (~SpecCell) | SpecObject, m_jit.branchPtr(
+        JSValueRegs(gpr), edge, (~SpecCell) | SpecObject, m_jit.branchPtr(
             MacroAssembler::Equal, 
             MacroAssembler::Address(gpr, JSCell::structureOffset()), 
             MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
@@ -4042,13 +4152,58 @@
         return;
     
     SpeculateCellOperand operand(this, edge);
+    GPRReg gpr = operand.gpr();
     DFG_TYPE_CHECK(
-        JSValueSource::unboxedCell(operand.gpr()), edge, SpecString, m_jit.branchPtr(
+        JSValueSource::unboxedCell(gpr), edge, SpecString, m_jit.branchPtr(
             MacroAssembler::NotEqual, 
-            MacroAssembler::Address(operand.gpr(), JSCell::structureOffset()), 
+            MacroAssembler::Address(gpr, JSCell::structureOffset()), 
             MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
 }
 
+void SpeculativeJIT::speculateStringObject(GPRReg gpr)
+{
+    speculateStringObjectForStructure(JITCompiler::Address(gpr, JSCell::structureOffset()));
+}
+
+void SpeculativeJIT::speculateStringObject(Edge edge)
+{
+    if (!needsTypeCheck(edge, SpecStringObject))
+        return;
+    
+    SpeculateCellOperand operand(this, edge);
+    GPRReg gpr = operand.gpr();
+    if (!needsTypeCheck(edge, SpecStringObject))
+        return;
+    
+    speculateStringObject(gpr);
+    m_state.forNode(edge).filter(SpecStringObject);
+}
+
+void SpeculativeJIT::speculateStringOrStringObject(Edge edge)
+{
+    if (!needsTypeCheck(edge, SpecString | SpecStringObject))
+        return;
+    
+    SpeculateCellOperand operand(this, edge);
+    GPRReg gpr = operand.gpr();
+    if (!needsTypeCheck(edge, SpecString | SpecStringObject))
+        return;
+    
+    GPRTemporary structure(this);
+    GPRReg structureGPR = structure.gpr();
+    
+    m_jit.loadPtr(JITCompiler::Address(gpr, JSCell::structureOffset()), structureGPR);
+    
+    JITCompiler::Jump isString = m_jit.branchPtr(
+        JITCompiler::Equal, structureGPR, TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
+    
+    speculateStringObjectForStructure(structureGPR);
+    
+    isString.link(&m_jit);
+    
+    m_state.forNode(edge).filter(SpecString | SpecStringObject);
+}
+
 void SpeculativeJIT::speculateNotCell(Edge edge)
 {
     if (!needsTypeCheck(edge, ~SpecCell))
@@ -4107,6 +4262,9 @@
     case KnownCellUse:
         ASSERT(!needsTypeCheck(edge, SpecCell));
         break;
+    case KnownStringUse:
+        ASSERT(!needsTypeCheck(edge, SpecString));
+        break;
     case Int32Use:
         speculateInt32(edge);
         break;
@@ -4131,6 +4289,12 @@
     case StringUse:
         speculateString(edge);
         break;
+    case StringObjectUse:
+        speculateStringObject(edge);
+        break;
+    case StringOrStringObjectUse:
+        speculateStringOrStringObject(edge);
+        break;
     case NotCellUse:
         speculateNotCell(edge);
         break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 8ea520c..e352d2e 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -1085,6 +1085,16 @@
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure));
         return appendCallWithExceptionCheckSetResult(operation, result);
     }
+    JITCompiler::Call callOperation(C_DFGOperation_EJssSt operation, GPRReg result, GPRReg arg1, Structure* structure)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(structure));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_DFGOperation_EJ operation, GPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
     JITCompiler::Call callOperation(S_DFGOperation_J operation, GPRReg result, GPRReg arg1)
     {
         m_jit.setupArguments(arg1);
@@ -1473,6 +1483,16 @@
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure));
         return appendCallWithExceptionCheckSetResult(operation, result);
     }
+    JITCompiler::Call callOperation(C_DFGOperation_EJssSt operation, GPRReg result, GPRReg arg1, Structure* structure)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(structure));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_DFGOperation_EJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
     JITCompiler::Call callOperation(S_DFGOperation_J operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
     {
         m_jit.setupArguments(arg1Payload, arg1Tag);
@@ -2031,6 +2051,9 @@
     void emitObjectOrOtherBranch(Edge value, BlockIndex taken, BlockIndex notTaken);
     void emitBranch(Node*);
     
+    void compileToStringOnCell(Node*);
+    void compileNewStringObject(Node*);
+    
     void compileIntegerCompare(Node*, MacroAssembler::RelationalCondition);
     void compileDoubleCompare(Node*, MacroAssembler::DoubleCondition);
     
@@ -2204,6 +2227,11 @@
     void speculateObject(Edge);
     void speculateObjectOrOther(Edge);
     void speculateString(Edge);
+    template<typename StructureLocationType>
+    void speculateStringObjectForStructure(StructureLocationType);
+    void speculateStringObject(GPRReg);
+    void speculateStringObject(Edge);
+    void speculateStringOrStringObject(Edge);
     void speculateNotCell(Edge);
     void speculateOther(Edge);
     void speculate(Node*, Edge);
@@ -2838,7 +2866,7 @@
         , m_gprOrInvalid(InvalidGPRReg)
     {
         ASSERT(m_jit);
-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == CellUse || edge.useKind() == KnownCellUse || edge.useKind() == ObjectUse || edge.useKind() == StringUse));
+        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == CellUse || edge.useKind() == KnownCellUse || edge.useKind() == ObjectUse || edge.useKind() == StringUse || edge.useKind() == KnownStringUse || edge.useKind() == StringObjectUse || edge.useKind() == StringOrStringObjectUse));
         if (jit->isFilled(node()))
             gpr();
     }
@@ -2924,6 +2952,21 @@
     GPRReg m_gprOrInvalid;
 };
 
+template<typename StructureLocationType>
+void SpeculativeJIT::speculateStringObjectForStructure(StructureLocationType structureLocation)
+{
+    Structure* stringObjectStructure =
+        m_jit.globalObjectFor(m_currentNode->codeOrigin)->stringObjectStructure();
+    Structure* stringPrototypeStructure = stringObjectStructure->storedPrototype().asCell()->structure();
+    ASSERT(stringPrototypeStructure->transitionWatchpointSetIsStillValid());
+    
+    speculationCheck(
+        NotStringObject, JSValueRegs(), 0,
+        m_jit.branchPtr(
+            JITCompiler::NotEqual, structureLocation, TrustedImmPtr(stringObjectStructure)));
+    stringPrototypeStructure->addTransitionWatchpoint(speculationWatchpoint(NotStringObject));
+}
+
 #define DFG_TYPE_CHECK(source, edge, typesPassedThrough, jumpToFail) do { \
         if (!needsTypeCheck((edge), (typesPassedThrough)))              \
             break;                                                      \
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index c13cf87..e56784c 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -1099,7 +1099,7 @@
 #endif
     AbstractValue& value = m_state.forNode(edge);
     SpeculatedType type = value.m_type;
-    ASSERT(edge.useKind() != KnownCellUse || !(value.m_type & ~SpecCell));
+    ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell));
     value.filter(SpecCell);
     VirtualRegister virtualRegister = edge->virtualRegister();
     GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -3258,58 +3258,73 @@
     }
         
     case ToPrimitive: {
-        switch (node->child1().useKind()) {
-        case Int32Use: {
-            // It's really profitable to speculate integer, since it's really cheap,
-            // it means we don't have to do any real work, and we emit a lot less code.
+        RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
+        JSValueOperand op1(this, node->child1());
+        GPRTemporary resultTag(this, op1);
+        GPRTemporary resultPayload(this, op1, false);
+        
+        GPRReg op1TagGPR = op1.tagGPR();
+        GPRReg op1PayloadGPR = op1.payloadGPR();
+        GPRReg resultTagGPR = resultTag.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        
+        op1.use();
+        
+        if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean))) {
+            m_jit.move(op1TagGPR, resultTagGPR);
+            m_jit.move(op1PayloadGPR, resultPayloadGPR);
+        } else {
+            MacroAssembler::Jump alreadyPrimitive = m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag));
+            MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1PayloadGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
             
-            SpeculateIntegerOperand op1(this, node->child1());
-            GPRTemporary result(this, op1);
+            alreadyPrimitive.link(&m_jit);
+            m_jit.move(op1TagGPR, resultTagGPR);
+            m_jit.move(op1PayloadGPR, resultPayloadGPR);
             
-            ASSERT(op1.format() == DataFormatInteger);
-            m_jit.move(op1.gpr(), result.gpr());
-            
-            integerResult(result.gpr(), node);
-            break;
+            addSlowPathGenerator(
+                slowPathCall(
+                    notPrimitive, this, operationToPrimitive,
+                    JSValueRegs(resultTagGPR, resultPayloadGPR), op1TagGPR, op1PayloadGPR));
         }
-
-        case UntypedUse: {
+        
+        jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
+        break;
+    }
+        
+    case ToString: {
+        if (node->child1().useKind() == UntypedUse) {
             JSValueOperand op1(this, node->child1());
-            GPRTemporary resultTag(this, op1);
-            GPRTemporary resultPayload(this, op1, false);
-        
-            GPRReg op1TagGPR = op1.tagGPR();
             GPRReg op1PayloadGPR = op1.payloadGPR();
-            GPRReg resultTagGPR = resultTag.gpr();
-            GPRReg resultPayloadGPR = resultPayload.gpr();
-        
-            op1.use();
-        
-            if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean))) {
-                m_jit.move(op1TagGPR, resultTagGPR);
-                m_jit.move(op1PayloadGPR, resultPayloadGPR);
-            } else {
-                MacroAssembler::Jump alreadyPrimitive = m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag));
-                MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1PayloadGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
+            GPRReg op1TagGPR = op1.tagGPR();
             
-                alreadyPrimitive.link(&m_jit);
-                m_jit.move(op1TagGPR, resultTagGPR);
-                m_jit.move(op1PayloadGPR, resultPayloadGPR);
+            GPRResult result(this);
+            GPRReg resultGPR = result.gpr();
             
-                addSlowPathGenerator(
-                    slowPathCall(
-                        notPrimitive, this, operationToPrimitive,
-                        JSValueRegs(resultTagGPR, resultPayloadGPR), op1TagGPR, op1PayloadGPR));
+            flushRegisters();
+            
+            JITCompiler::Jump done;
+            if (node->child1()->prediction() & SpecString) {
+                JITCompiler::Jump slowPath = m_jit.branch32(
+                    JITCompiler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag));
+                done = m_jit.branchPtr(
+                    JITCompiler::Equal,
+                    JITCompiler::Address(op1PayloadGPR, JSCell::structureOffset()),
+                    TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
+                slowPath.link(&m_jit);
             }
+            callOperation(operationToString, resultGPR, op1TagGPR, op1PayloadGPR);
+            if (done.isSet())
+                done.link(&m_jit);
+            cellResult(resultGPR, node);
+            break;
+        }
         
-            jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
-            break;
-        }
-            
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
+        compileToStringOnCell(node);
+        break;
+    }
+        
+    case NewStringObject: {
+        compileNewStringObject(node);
         break;
     }
         
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 087aaa2..157549e 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -1125,7 +1125,7 @@
 #endif
     AbstractValue& value = m_state.forNode(edge);
     SpeculatedType type = value.m_type;
-    ASSERT(edge.useKind() != KnownCellUse || !(value.m_type & ~SpecCell));
+    ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell));
     value.filter(SpecCell);
     VirtualRegister virtualRegister = edge->virtualRegister();
     GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -3188,52 +3188,65 @@
     }
         
     case ToPrimitive: {
-        switch (node->child1().useKind()) {
-        case Int32Use: {
-            // It's really profitable to speculate integer, since it's really cheap,
-            // it means we don't have to do any real work, and we emit a lot less code.
+        RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
+        JSValueOperand op1(this, node->child1());
+        GPRTemporary result(this, op1);
+        
+        GPRReg op1GPR = op1.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        op1.use();
+        
+        if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean)))
+            m_jit.move(op1GPR, resultGPR);
+        else {
+            MacroAssembler::Jump alreadyPrimitive = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
+            MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
             
-            SpeculateIntegerOperand op1(this, node->child1());
-            GPRTemporary result(this, op1);
+            alreadyPrimitive.link(&m_jit);
+            m_jit.move(op1GPR, resultGPR);
             
-            m_jit.move(op1.gpr(), result.gpr());
-            if (op1.format() == DataFormatInteger)
-                m_jit.or64(GPRInfo::tagTypeNumberRegister, result.gpr());
-            
-            jsValueResult(result.gpr(), node);
-            break;
+            addSlowPathGenerator(
+                slowPathCall(notPrimitive, this, operationToPrimitive, resultGPR, op1GPR));
         }
         
-        case UntypedUse: {
+        jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
+        break;
+    }
+        
+    case ToString: {
+        if (node->child1().useKind() == UntypedUse) {
             JSValueOperand op1(this, node->child1());
-            GPRTemporary result(this, op1);
-        
             GPRReg op1GPR = op1.gpr();
+            
+            GPRResult result(this);
             GPRReg resultGPR = result.gpr();
-        
-            op1.use();
-        
-            if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean)))
-                m_jit.move(op1GPR, resultGPR);
-            else {
-                MacroAssembler::Jump alreadyPrimitive = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
-                MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
             
-                alreadyPrimitive.link(&m_jit);
-                m_jit.move(op1GPR, resultGPR);
+            flushRegisters();
             
-                addSlowPathGenerator(
-                    slowPathCall(notPrimitive, this, operationToPrimitive, resultGPR, op1GPR));
+            JITCompiler::Jump done;
+            if (node->child1()->prediction() & SpecString) {
+                JITCompiler::Jump slowPath = m_jit.branchTest64(
+                    JITCompiler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
+                done = m_jit.branchPtr(
+                    JITCompiler::Equal,
+                    JITCompiler::Address(op1GPR, JSCell::structureOffset()),
+                    TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
+                slowPath.link(&m_jit);
             }
+            callOperation(operationToString, resultGPR, op1GPR);
+            if (done.isSet())
+                done.link(&m_jit);
+            cellResult(resultGPR, node);
+            break;
+        }
         
-            jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
-            break;
-        }
-            
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
+        compileToStringOnCell(node);
+        break;
+    }
+        
+    case NewStringObject: {
+        compileNewStringObject(node);
         break;
     }
         
diff --git a/Source/JavaScriptCore/dfg/DFGUseKind.cpp b/Source/JavaScriptCore/dfg/DFGUseKind.cpp
index bb81920..bfba754 100644
--- a/Source/JavaScriptCore/dfg/DFGUseKind.cpp
+++ b/Source/JavaScriptCore/dfg/DFGUseKind.cpp
@@ -71,6 +71,15 @@
     case StringUse:
         out.print("String");
         break;
+    case KnownStringUse:
+        out.print("KnownString");
+        break;
+    case StringObjectUse:
+        out.print("StringObject");
+        break;
+    case StringOrStringObjectUse:
+        out.print("StringOrStringObject");
+        break;
     case NotCellUse:
         out.print("NotCell");
         break;
diff --git a/Source/JavaScriptCore/dfg/DFGUseKind.h b/Source/JavaScriptCore/dfg/DFGUseKind.h
index 74b0ca2..afe3d354 100644
--- a/Source/JavaScriptCore/dfg/DFGUseKind.h
+++ b/Source/JavaScriptCore/dfg/DFGUseKind.h
@@ -48,6 +48,9 @@
     ObjectUse,
     ObjectOrOtherUse,
     StringUse,
+    KnownStringUse,
+    StringObjectUse,
+    StringOrStringObjectUse,
     NotCellUse,
     OtherUse,
     LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements.
@@ -76,7 +79,12 @@
     case ObjectOrOtherUse:
         return SpecObject | SpecOther;
     case StringUse:
+    case KnownStringUse:
         return SpecString;
+    case StringObjectUse:
+        return SpecStringObject;
+    case StringOrStringObjectUse:
+        return SpecString | SpecStringObject;
     case NotCellUse:
         return ~SpecCell;
     case OtherUse:
diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h
index 9852b31..716115ba 100644
--- a/Source/JavaScriptCore/interpreter/CallFrame.h
+++ b/Source/JavaScriptCore/interpreter/CallFrame.h
@@ -94,7 +94,6 @@
         static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; }
         static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; }
         static const HashTable* regExpPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().regExpPrototypeTable; }
-        static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; }
         static const HashTable* stringConstructorTable(CallFrame* callFrame) { return callFrame->globalData().stringConstructorTable; }
 
         static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
diff --git a/Source/JavaScriptCore/runtime/Intrinsic.h b/Source/JavaScriptCore/runtime/Intrinsic.h
index 73244e7..76fb92a 100644
--- a/Source/JavaScriptCore/runtime/Intrinsic.h
+++ b/Source/JavaScriptCore/runtime/Intrinsic.h
@@ -47,6 +47,7 @@
     LogIntrinsic,
     RegExpExecIntrinsic,
     RegExpTestIntrinsic,
+    StringPrototypeValueOfIntrinsic
 };
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSDestructibleObject.h b/Source/JavaScriptCore/runtime/JSDestructibleObject.h
index b8479be..7eb4548 100644
--- a/Source/JavaScriptCore/runtime/JSDestructibleObject.h
+++ b/Source/JavaScriptCore/runtime/JSDestructibleObject.h
@@ -14,6 +14,8 @@
     static const bool needsDestruction = true;
 
     const ClassInfo* classInfo() const { return m_classInfo; }
+    
+    static ptrdiff_t classInfoOffset() { return OBJECT_OFFSETOF(JSDestructibleObject, m_classInfo); }
 
 protected:
     JSDestructibleObject(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly = 0)
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
index 36f2ffd..7ff2de1 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -97,7 +97,6 @@
 extern const HashTable regExpTable;
 extern const HashTable regExpConstructorTable;
 extern const HashTable regExpPrototypeTable;
-extern const HashTable stringTable;
 extern const HashTable stringConstructorTable;
 
 // Note: Platform.h will enforce that ENABLE(ASSEMBLER) is true if either
@@ -158,7 +157,6 @@
     , regExpTable(fastNew<HashTable>(JSC::regExpTable))
     , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
     , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable))
-    , stringTable(fastNew<HashTable>(JSC::stringTable))
     , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable))
     , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
     , propertyNames(new CommonIdentifiers(this))
@@ -288,7 +286,6 @@
     regExpTable->deleteTable();
     regExpConstructorTable->deleteTable();
     regExpPrototypeTable->deleteTable();
-    stringTable->deleteTable();
     stringConstructorTable->deleteTable();
 
     fastDelete(const_cast<HashTable*>(arrayConstructorTable));
@@ -307,7 +304,6 @@
     fastDelete(const_cast<HashTable*>(regExpTable));
     fastDelete(const_cast<HashTable*>(regExpConstructorTable));
     fastDelete(const_cast<HashTable*>(regExpPrototypeTable));
-    fastDelete(const_cast<HashTable*>(stringTable));
     fastDelete(const_cast<HashTable*>(stringConstructorTable));
 
     opaqueJSClassData.clear();
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
index 570d85d..9a59d14 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
@@ -230,7 +230,6 @@
         const HashTable* regExpTable;
         const HashTable* regExpConstructorTable;
         const HashTable* regExpPrototypeTable;
-        const HashTable* stringTable;
         const HashTable* stringConstructorTable;
         
         Strong<Structure> structureStructure;
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index bd88b4d..bb87763 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2012 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Eric Seidel (eric@webkit.org)
  *
  *  This library is free software; you can redistribute it and/or
@@ -30,6 +30,7 @@
 #include "CopyVisitorInlines.h"
 #include "DatePrototype.h"
 #include "ErrorConstructor.h"
+#include "Executable.h"
 #include "GetterSetter.h"
 #include "IndexingHeaderInlines.h"
 #include "JSFunction.h"
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index d8532b1..17566f8 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -1454,10 +1454,16 @@
 // Helper for defining native functions, if you're not using a static hash table.
 // Use this macro from within finishCreation() methods in prototypes. This assumes
 // you've defined variables called exec, globalObject, and globalData, and they
-// have the expected meanings. This also assumes that the function you're defining
-// doesn't have an intrinsic.
+// have the expected meanings.
+#define JSC_NATIVE_INTRINSIC_FUNCTION(jsName, cppName, attributes, length, intrinsic) \
+    putDirectNativeFunction(\
+        exec, globalObject, Identifier(exec, #jsName), (length), cppName, \
+        (intrinsic), (attributes))
+
+// As above, but this assumes that the function you're defining doesn't have an
+// intrinsic.
 #define JSC_NATIVE_FUNCTION(jsName, cppName, attributes, length) \
-    putDirectNativeFunction(exec, globalObject, globalData.propertyNames->jsName, (length), cppName, NoIntrinsic, (attributes))
+    JSC_NATIVE_INTRINSIC_FUNCTION(jsName, cppName, (attributes), (length), NoIntrinsic)
 
 } // namespace JSC
 
diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.h b/Source/JavaScriptCore/runtime/JSWrapperObject.h
index 72bc187..f108c9e 100644
--- a/Source/JavaScriptCore/runtime/JSWrapperObject.h
+++ b/Source/JavaScriptCore/runtime/JSWrapperObject.h
@@ -32,6 +32,12 @@
     public:
         typedef JSDestructibleObject Base;
 
+        static size_t allocationSize(size_t inlineCapacity)
+        {
+            ASSERT_UNUSED(inlineCapacity, !inlineCapacity);
+            return sizeof(JSWrapperObject);
+        }
+
         JSValue internalValue() const;
         void setInternalValue(JSGlobalData&, JSValue);
 
@@ -39,6 +45,16 @@
         { 
             return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
+        
+        static ptrdiff_t internalValueOffset() { return OBJECT_OFFSETOF(JSWrapperObject, m_internalValue); }
+        static ptrdiff_t internalValueCellOffset()
+        {
+#if USE(JSVALUE64)
+            return internalValueOffset();
+#else
+            return internalValueOffset() + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload);
+#endif
+        }
 
     protected:
         explicit JSWrapperObject(JSGlobalData&, Structure*);
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp
index 25f9897..d810812 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
  *  Copyright (C) 2009 Torch Mobile, Inc.
  *
  *  This library is free software; you can redistribute it and/or
@@ -82,56 +82,7 @@
 static EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState*);
 static EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*);
 
-}
-
-#include "StringPrototype.lut.h"
-
-namespace JSC {
-
-const ClassInfo StringPrototype::s_info = { "String", &StringObject::s_info, 0, ExecState::stringTable, CREATE_METHOD_TABLE(StringPrototype) };
-
-/* Source for StringPrototype.lut.h
-@begin stringTable 26
-    toString              stringProtoFuncToString          DontEnum|Function       0
-    valueOf               stringProtoFuncToString          DontEnum|Function       0
-    charAt                stringProtoFuncCharAt            DontEnum|Function       1
-    charCodeAt            stringProtoFuncCharCodeAt        DontEnum|Function       1
-    concat                stringProtoFuncConcat            DontEnum|Function       1
-    indexOf               stringProtoFuncIndexOf           DontEnum|Function       1
-    lastIndexOf           stringProtoFuncLastIndexOf       DontEnum|Function       1
-    match                 stringProtoFuncMatch             DontEnum|Function       1
-    replace               stringProtoFuncReplace           DontEnum|Function       2
-    search                stringProtoFuncSearch            DontEnum|Function       1
-    slice                 stringProtoFuncSlice             DontEnum|Function       2
-    split                 stringProtoFuncSplit             DontEnum|Function       2
-    substr                stringProtoFuncSubstr            DontEnum|Function       2
-    substring             stringProtoFuncSubstring         DontEnum|Function       2
-    toLowerCase           stringProtoFuncToLowerCase       DontEnum|Function       0
-    toUpperCase           stringProtoFuncToUpperCase       DontEnum|Function       0
-    localeCompare         stringProtoFuncLocaleCompare     DontEnum|Function       1
-
-    # toLocaleLowerCase and toLocaleUpperCase are currently identical to toLowerCase and toUpperCase
-    toLocaleLowerCase     stringProtoFuncToLowerCase       DontEnum|Function       0
-    toLocaleUpperCase     stringProtoFuncToUpperCase       DontEnum|Function       0
-
-    big                   stringProtoFuncBig               DontEnum|Function       0
-    small                 stringProtoFuncSmall             DontEnum|Function       0
-    blink                 stringProtoFuncBlink             DontEnum|Function       0
-    bold                  stringProtoFuncBold              DontEnum|Function       0
-    fixed                 stringProtoFuncFixed             DontEnum|Function       0
-    italics               stringProtoFuncItalics           DontEnum|Function       0
-    strike                stringProtoFuncStrike            DontEnum|Function       0
-    sub                   stringProtoFuncSub               DontEnum|Function       0
-    sup                   stringProtoFuncSup               DontEnum|Function       0
-    fontcolor             stringProtoFuncFontcolor         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
-*/
+const ClassInfo StringPrototype::s_info = { "String", &StringObject::s_info, 0, 0, CREATE_METHOD_TABLE(StringPrototype) };
 
 // ECMA 15.5.4
 StringPrototype::StringPrototype(ExecState* exec, Structure* structure)
@@ -139,23 +90,59 @@
 {
 }
 
-void StringPrototype::finishCreation(ExecState* exec, JSGlobalObject*, JSString* nameAndMessage)
+void StringPrototype::finishCreation(ExecState* exec, JSGlobalObject* globalObject, JSString* nameAndMessage)
 {
-    Base::finishCreation(exec->globalData(), nameAndMessage);
+    JSGlobalData& globalData = exec->globalData();
+    
+    Base::finishCreation(globalData, nameAndMessage);
     ASSERT(inherits(&s_info));
 
+    JSC_NATIVE_INTRINSIC_FUNCTION(toString, stringProtoFuncToString, DontEnum, 0, StringPrototypeValueOfIntrinsic);
+    JSC_NATIVE_INTRINSIC_FUNCTION(valueOf, stringProtoFuncToString, DontEnum, 0, StringPrototypeValueOfIntrinsic);
+    JSC_NATIVE_INTRINSIC_FUNCTION(charAt, stringProtoFuncCharAt, DontEnum, 1, CharAtIntrinsic);
+    JSC_NATIVE_INTRINSIC_FUNCTION(charCodeAt, stringProtoFuncCharCodeAt, DontEnum, 1, CharCodeAtIntrinsic);
+    JSC_NATIVE_FUNCTION(concat, stringProtoFuncConcat, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(indexOf, stringProtoFuncIndexOf, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(lastIndexOf, stringProtoFuncLastIndexOf, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(match, stringProtoFuncMatch, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(replace, stringProtoFuncReplace, DontEnum, 2);
+    JSC_NATIVE_FUNCTION(search, stringProtoFuncSearch, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(slice, stringProtoFuncSlice, DontEnum, 2);
+    JSC_NATIVE_FUNCTION(split, stringProtoFuncSplit, DontEnum, 2);
+    JSC_NATIVE_FUNCTION(substr, stringProtoFuncSubstr, DontEnum, 2);
+    JSC_NATIVE_FUNCTION(substring, stringProtoFuncSubstring, DontEnum, 2);
+    JSC_NATIVE_FUNCTION(toLowerCase, stringProtoFuncToLowerCase, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(toUpperCase, stringProtoFuncToUpperCase, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(localeCompare, stringProtoFuncLocaleCompare, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(toLocaleLowerCase, stringProtoFuncToLowerCase, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(toLocaleUpperCase, stringProtoFuncToUpperCase, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(big, stringProtoFuncBig, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(small, stringProtoFuncSmall, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(blink, stringProtoFuncBlink, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(bold, stringProtoFuncBold, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(fixed, stringProtoFuncFixed, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(italics, stringProtoFuncItalics, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(strike, stringProtoFuncStrike, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(sub, stringProtoFuncSub, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(sup, stringProtoFuncSup, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(fontcolor, stringProtoFuncFontcolor, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(fontsize, stringProtoFuncFontsize, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(anchor, stringProtoFuncAnchor, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(link, stringProtoFuncLink, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(trim, stringProtoFuncTrim, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(trimLeft, stringProtoFuncTrimLeft, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(trimRight, stringProtoFuncTrimRight, DontEnum, 0);
+
     // The constructor will be added later, after StringConstructor has been built
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
 }
 
-bool StringPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
+StringPrototype* StringPrototype::create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
 {
-    return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), jsCast<StringPrototype*>(cell), propertyName, slot);
-}
-
-bool StringPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
-{
-    return getStaticFunctionDescriptor<StringObject>(exec, ExecState::stringTable(exec), jsCast<StringPrototype*>(object), propertyName, descriptor);
+    JSString* empty = jsEmptyString(exec);
+    StringPrototype* prototype = new (NotNull, allocateCell<StringPrototype>(*exec->heap())) StringPrototype(exec, structure);
+    prototype->finishCreation(exec, globalObject, empty);
+    return prototype;
 }
 
 // ------------------------------ Functions --------------------------
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.h b/Source/JavaScriptCore/runtime/StringPrototype.h
index b846c7b..6d36804 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.h
+++ b/Source/JavaScriptCore/runtime/StringPrototype.h
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007, 2008, 2013 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
@@ -34,16 +34,7 @@
     public:
         typedef StringObject Base;
 
-        static StringPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
-        {
-            JSString* empty = jsEmptyString(exec);
-            StringPrototype* prototype = new (NotNull, allocateCell<StringPrototype>(*exec->heap())) StringPrototype(exec, structure);
-            prototype->finishCreation(exec, globalObject, empty);
-            return prototype;
-        }
-
-        static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
-        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
+        static StringPrototype* create(ExecState*, JSGlobalObject*, Structure*);
 
         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
@@ -54,7 +45,7 @@
         
     protected:
         void finishCreation(ExecState*, JSGlobalObject*, JSString*);
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | StringObject::StructureFlags;
+        static const unsigned StructureFlags = StringObject::StructureFlags;
 
     };