Title: [120897] trunk/Source/_javascript_Core
Revision
120897
Author
[email protected]
Date
2012-06-20 18:38:49 -0700 (Wed, 20 Jun 2012)

Log Message

DFG should optimize ResolveGlobal
https://bugs.webkit.org/show_bug.cgi?id=89617

Reviewed by Oliver Hunt.
        
This adds inlining of ResolveGlobal accesses that are known monomorphic. It also
adds the specific function optimization to ResolveGlobal, when it is inlined. And,
it makes internal functions act like specific functions, since that will be the
most common use-case of this optimization.
        
This is only a slighy speed-up (sub 1%), since we don't yet do the obvious thing
with this optimization, which is to completely inline common "globally resolved"
function and constructor calls, like "new Array()".

* CMakeLists.txt:
* GNUmakefile.list.am:
* _javascript_Core.vcproj/_javascript_Core/_javascript_Core.def:
* _javascript_Core.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::globalResolveInfoForBytecodeOffset):
* bytecode/CodeBlock.h:
(CodeBlock):
(JSC::CodeBlock::numberOfGlobalResolveInfos):
* bytecode/GlobalResolveInfo.h:
(JSC::getGlobalResolveInfoBytecodeOffset):
(JSC):
* bytecode/ResolveGlobalStatus.cpp: Added.
(JSC):
(JSC::computeForStructure):
(JSC::computeForLLInt):
(JSC::ResolveGlobalStatus::computeFor):
* bytecode/ResolveGlobalStatus.h: Added.
(JSC):
(ResolveGlobalStatus):
(JSC::ResolveGlobalStatus::ResolveGlobalStatus):
(JSC::ResolveGlobalStatus::state):
(JSC::ResolveGlobalStatus::isSet):
(JSC::ResolveGlobalStatus::operator!):
(JSC::ResolveGlobalStatus::isSimple):
(JSC::ResolveGlobalStatus::takesSlowPath):
(JSC::ResolveGlobalStatus::structure):
(JSC::ResolveGlobalStatus::offset):
(JSC::ResolveGlobalStatus::specificValue):
* dfg/DFGByteCodeParser.cpp:
(ByteCodeParser):
(JSC::DFG::ByteCodeParser::handleGetByOffset):
(DFG):
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::parseBlock):
* runtime/JSObject.cpp:
(JSC::getCallableObjectSlow):
(JSC):
(JSC::JSObject::put):
(JSC::JSObject::putDirectVirtual):
(JSC::JSObject::putDirectAccessor):
* runtime/JSObject.h:
(JSC):
(JSC::getCallableObject):
(JSC::JSObject::putOwnDataProperty):
(JSC::JSObject::putDirect):
(JSC::JSObject::putDirectWithoutTransition):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (120896 => 120897)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2012-06-21 01:38:49 UTC (rev 120897)
@@ -54,6 +54,7 @@
     bytecode/PolymorphicPutByIdList.cpp
     bytecode/SpeculatedType.cpp
     bytecode/PutByIdStatus.cpp
+    bytecode/ResolveGlobalStatus.cpp
     bytecode/SamplingTool.cpp
     bytecode/StructureStubInfo.cpp
     bytecode/Watchpoint.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (120896 => 120897)


--- trunk/Source/_javascript_Core/ChangeLog	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-06-21 01:38:49 UTC (rev 120897)
@@ -1,5 +1,70 @@
 2012-06-20  Filip Pizlo  <[email protected]>
 
+        DFG should optimize ResolveGlobal
+        https://bugs.webkit.org/show_bug.cgi?id=89617
+
+        Reviewed by Oliver Hunt.
+        
+        This adds inlining of ResolveGlobal accesses that are known monomorphic. It also
+        adds the specific function optimization to ResolveGlobal, when it is inlined. And,
+        it makes internal functions act like specific functions, since that will be the
+        most common use-case of this optimization.
+        
+        This is only a slighy speed-up (sub 1%), since we don't yet do the obvious thing
+        with this optimization, which is to completely inline common "globally resolved"
+        function and constructor calls, like "new Array()".
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * _javascript_Core.vcproj/_javascript_Core/_javascript_Core.def:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * Target.pri:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::globalResolveInfoForBytecodeOffset):
+        * bytecode/CodeBlock.h:
+        (CodeBlock):
+        (JSC::CodeBlock::numberOfGlobalResolveInfos):
+        * bytecode/GlobalResolveInfo.h:
+        (JSC::getGlobalResolveInfoBytecodeOffset):
+        (JSC):
+        * bytecode/ResolveGlobalStatus.cpp: Added.
+        (JSC):
+        (JSC::computeForStructure):
+        (JSC::computeForLLInt):
+        (JSC::ResolveGlobalStatus::computeFor):
+        * bytecode/ResolveGlobalStatus.h: Added.
+        (JSC):
+        (ResolveGlobalStatus):
+        (JSC::ResolveGlobalStatus::ResolveGlobalStatus):
+        (JSC::ResolveGlobalStatus::state):
+        (JSC::ResolveGlobalStatus::isSet):
+        (JSC::ResolveGlobalStatus::operator!):
+        (JSC::ResolveGlobalStatus::isSimple):
+        (JSC::ResolveGlobalStatus::takesSlowPath):
+        (JSC::ResolveGlobalStatus::structure):
+        (JSC::ResolveGlobalStatus::offset):
+        (JSC::ResolveGlobalStatus::specificValue):
+        * dfg/DFGByteCodeParser.cpp:
+        (ByteCodeParser):
+        (JSC::DFG::ByteCodeParser::handleGetByOffset):
+        (DFG):
+        (JSC::DFG::ByteCodeParser::handleGetById):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * runtime/JSObject.cpp:
+        (JSC::getCallableObjectSlow):
+        (JSC):
+        (JSC::JSObject::put):
+        (JSC::JSObject::putDirectVirtual):
+        (JSC::JSObject::putDirectAccessor):
+        * runtime/JSObject.h:
+        (JSC):
+        (JSC::getCallableObject):
+        (JSC::JSObject::putOwnDataProperty):
+        (JSC::JSObject::putDirect):
+        (JSC::JSObject::putDirectWithoutTransition):
+
+2012-06-20  Filip Pizlo  <[email protected]>
+
         Functions on global objects should be specializable
         https://bugs.webkit.org/show_bug.cgi?id=89615
 

Modified: trunk/Source/_javascript_Core/GNUmakefile.list.am (120896 => 120897)


--- trunk/Source/_javascript_Core/GNUmakefile.list.am	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/GNUmakefile.list.am	2012-06-21 01:38:49 UTC (rev 120897)
@@ -126,6 +126,8 @@
 	Source/_javascript_Core/bytecode/PutByIdStatus.cpp \
 	Source/_javascript_Core/bytecode/PutByIdStatus.h \
 	Source/_javascript_Core/bytecode/PutKind.h \
+	Source/_javascript_Core/bytecode/ResolveGlobalStatus.cpp \
+	Source/_javascript_Core/bytecode/ResolveGlobalStatus.h \
 	Source/_javascript_Core/bytecode/SamplingTool.cpp \
 	Source/_javascript_Core/bytecode/SamplingTool.h \
 	Source/_javascript_Core/bytecode/StructureSet.h \

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def (120896 => 120897)


--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def	2012-06-21 01:38:49 UTC (rev 120897)
@@ -189,6 +189,7 @@
     ?get@Structure@JSC@@QAEIAAVJSGlobalData@2@VPropertyName@2@AAIAAPAVJSCell@2@@Z
     ?getCalculatedDisplayName@JSC@@YA?AVUString@1@PAVExecState@1@PAVJSObject@1@@Z
     ?getCallData@JSCell@JSC@@SA?AW4CallType@2@PAV12@AATCallData@2@@Z
+    ?getCallableObjectSlow@JSC@@YAPAVJSCell@1@PAV21@@Z
     ?getConstructData@JSCell@JSC@@SA?AW4ConstructType@2@PAV12@AATConstructData@2@@Z
     ?getCurrentLocalTime@WTF@@YAXPAUtm@@@Z
     ?getObject@JSCell@JSC@@QAEPAVJSObject@2@XZ

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (120896 => 120897)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2012-06-21 01:38:49 UTC (rev 120897)
@@ -211,6 +211,8 @@
 		0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */; };
 		0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */; };
 		0FF427651591A1CE004CB9FF /* DFGDisassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF427621591A1C9004CB9FF /* DFGDisassembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		0FF42771159275D5004CB9FF /* ResolveGlobalStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4276E159275D2004CB9FF /* ResolveGlobalStatus.cpp */; };
+		0FF42772159275D8004CB9FF /* ResolveGlobalStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4276F159275D2004CB9FF /* ResolveGlobalStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FF922D414F46B410041A24E /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; };
 		0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */; };
 		0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -933,6 +935,8 @@
 		0FF4275615914A20004CB9FF /* LinkBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkBuffer.cpp; sourceTree = "<group>"; };
 		0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDisassembler.cpp; path = dfg/DFGDisassembler.cpp; sourceTree = "<group>"; };
 		0FF427621591A1C9004CB9FF /* DFGDisassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDisassembler.h; path = dfg/DFGDisassembler.h; sourceTree = "<group>"; };
+		0FF4276E159275D2004CB9FF /* ResolveGlobalStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResolveGlobalStatus.cpp; sourceTree = "<group>"; };
+		0FF4276F159275D2004CB9FF /* ResolveGlobalStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResolveGlobalStatus.h; sourceTree = "<group>"; };
 		0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
 		0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCFAPhase.cpp; path = dfg/DFGCFAPhase.cpp; sourceTree = "<group>"; };
 		0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFAPhase.h; path = dfg/DFGCFAPhase.h; sourceTree = "<group>"; };
@@ -2347,6 +2351,8 @@
 				0F93329814CA7DC10085F3C6 /* MethodCallLinkStatus.h */,
 				0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
 				0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
+				0FF4276E159275D2004CB9FF /* ResolveGlobalStatus.cpp */,
+				0FF4276F159275D2004CB9FF /* ResolveGlobalStatus.h */,
 				0F93329B14CA7DC10085F3C6 /* StructureSet.h */,
 				0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */,
 				0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */,
@@ -2766,6 +2772,7 @@
 				0FF42749158EBE91004CB9FF /* udis86_types.h in Headers */,
 				0FF4274B158EBE91004CB9FF /* udis86.h in Headers */,
 				0FF427651591A1CE004CB9FF /* DFGDisassembler.h in Headers */,
+				0FF42772159275D8004CB9FF /* ResolveGlobalStatus.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3353,6 +3360,7 @@
 				0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */,
 				C2D58C3415912FEE0021A844 /* GCActivityCallback.cpp in Sources */,
 				0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */,
+				0FF42771159275D5004CB9FF /* ResolveGlobalStatus.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Source/_javascript_Core/Target.pri (120896 => 120897)


--- trunk/Source/_javascript_Core/Target.pri	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/Target.pri	2012-06-21 01:38:49 UTC (rev 120897)
@@ -64,6 +64,7 @@
     bytecode/Opcode.cpp \
     bytecode/PolymorphicPutByIdList.cpp \
     bytecode/PutByIdStatus.cpp \
+    bytecode/ResolveGlobalStatus.cpp \
     bytecode/SamplingTool.cpp \
     bytecode/SpeculatedType.cpp \
     bytecode/StructureStubInfo.cpp \

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (120896 => 120897)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2012-06-21 01:38:49 UTC (rev 120897)
@@ -2258,6 +2258,10 @@
         return false;
     return true;
 }
+GlobalResolveInfo& CodeBlock::globalResolveInfoForBytecodeOffset(unsigned bytecodeOffset)
+{
+    return *(binarySearch<GlobalResolveInfo, unsigned, getGlobalResolveInfoBytecodeOffset>(m_globalResolveInfos.begin(), m_globalResolveInfos.size(), bytecodeOffset));
+}
 #endif
 
 void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (120896 => 120897)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2012-06-21 01:38:49 UTC (rev 120897)
@@ -553,6 +553,8 @@
         }
         GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; }
         bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset);
+        GlobalResolveInfo& globalResolveInfoForBytecodeOffset(unsigned bytecodeOffset);
+        unsigned numberOfGlobalResolveInfos() { return m_globalResolveInfos.size(); }
 
         void setNumberOfCallLinkInfos(size_t size) { m_callLinkInfos.grow(size); }
         size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }

Modified: trunk/Source/_javascript_Core/bytecode/GlobalResolveInfo.h (120896 => 120897)


--- trunk/Source/_javascript_Core/bytecode/GlobalResolveInfo.h	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/bytecode/GlobalResolveInfo.h	2012-06-21 01:38:49 UTC (rev 120897)
@@ -42,6 +42,11 @@
     unsigned bytecodeOffset;
 };
 
+inline unsigned getGlobalResolveInfoBytecodeOffset(GlobalResolveInfo* globalResolveInfo)
+{
+    return globalResolveInfo->bytecodeOffset;
+}
+
 } // namespace JSC
 
 #endif // GlobalResolveInfo_h

Added: trunk/Source/_javascript_Core/bytecode/ResolveGlobalStatus.cpp (0 => 120897)


--- trunk/Source/_javascript_Core/bytecode/ResolveGlobalStatus.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/ResolveGlobalStatus.cpp	2012-06-21 01:38:49 UTC (rev 120897)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "ResolveGlobalStatus.h"
+
+#include "CodeBlock.h"
+#include "JSValue.h"
+#include "Structure.h"
+
+namespace JSC {
+
+static ResolveGlobalStatus computeForStructure(CodeBlock* codeBlock, Structure* structure, Identifier& identifier)
+{
+    unsigned attributesIgnored;
+    JSCell* specificValue;
+    size_t offset = structure->get(
+        *codeBlock->globalData(), identifier, attributesIgnored, specificValue);
+    if (offset == notFound)
+        return ResolveGlobalStatus();
+    
+    return ResolveGlobalStatus(ResolveGlobalStatus::Simple, structure, offset, specificValue);
+}
+
+static ResolveGlobalStatus computeForLLInt(CodeBlock* codeBlock, unsigned bytecodeIndex, Identifier& identifier)
+{
+#if ENABLE(LLINT)
+    Instruction* instruction = codeBlock->instructions().begin() + bytecodeIndex;
+    
+    ASSERT(instruction[0].u.opcode == llint_op_resolve_global);
+    
+    Structure* structure = instruction[3].u.structure.get();
+    if (!structure)
+        return ResolveGlobalStatus();
+    
+    return computeForStructure(codeBlock, structure, identifier);
+#else
+    UNUSED_PARAM(codeBlock);
+    UNUSED_PARAM(bytecodeIndex);
+    UNUSED_PARAM(identifier);
+    return ResolveGlobalStatus();
+#endif
+}
+
+ResolveGlobalStatus ResolveGlobalStatus::computeFor(CodeBlock* codeBlock, unsigned bytecodeIndex, Identifier& identifier)
+{
+#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+    if (!codeBlock->numberOfGlobalResolveInfos())
+        return computeForLLInt(codeBlock, bytecodeIndex, identifier);
+    
+    if (codeBlock->likelyToTakeSlowCase(bytecodeIndex))
+        return ResolveGlobalStatus(TakesSlowPath);
+    
+    GlobalResolveInfo& globalResolveInfo = codeBlock->globalResolveInfoForBytecodeOffset(bytecodeIndex);
+    
+    if (!globalResolveInfo.structure)
+        return computeForLLInt(codeBlock, bytecodeIndex, identifier);
+    
+    return computeForStructure(codeBlock, globalResolveInfo.structure.get(), identifier);
+#else
+    return computeForLLInt(codeBlock, bytecodeIndex, identifier);
+#endif
+}
+
+} // namespace JSC
+

Added: trunk/Source/_javascript_Core/bytecode/ResolveGlobalStatus.h (0 => 120897)


--- trunk/Source/_javascript_Core/bytecode/ResolveGlobalStatus.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/ResolveGlobalStatus.h	2012-06-21 01:38:49 UTC (rev 120897)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ResolveGlobalStatus_h
+#define ResolveGlobalStatus_h
+
+#include "JSValue.h"
+#include <wtf/NotFound.h>
+
+namespace JSC {
+
+class CodeBlock;
+class Identifier;
+class Structure;
+
+class ResolveGlobalStatus {
+public:
+    enum State {
+        NoInformation,
+        Simple,
+        TakesSlowPath
+    };
+    
+    ResolveGlobalStatus()
+        : m_state(NoInformation)
+        , m_structure(0)
+        , m_offset(notFound)
+    {
+    }
+    
+    ResolveGlobalStatus(
+        State state, Structure* structure = 0, size_t offset = notFound,
+        JSValue specificValue = JSValue())
+        : m_state(state)
+        , m_structure(structure)
+        , m_offset(offset)
+        , m_specificValue(specificValue)
+    {
+    }
+    
+    static ResolveGlobalStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+    
+    State state() const { return m_state; }
+    
+    bool isSet() const { return m_state != NoInformation; }
+    bool operator!() const { return !isSet(); }
+    bool isSimple() const { return m_state == Simple; }
+    bool takesSlowPath() const { return m_state == TakesSlowPath; }
+    
+    Structure* structure() const { return m_structure; }
+    size_t offset() const { return m_offset; }
+    JSValue specificValue() const { return m_specificValue; }
+
+private:
+    State m_state;
+    Structure* m_structure;
+    size_t m_offset;
+    JSValue m_specificValue;
+}; // class ResolveGlobalStatus
+
+} // namespace JSC
+
+#endif // ResolveGlobalStatus_h
+

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (120896 => 120897)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-06-21 01:38:49 UTC (rev 120897)
@@ -35,6 +35,7 @@
 #include "GetByIdStatus.h"
 #include "MethodCallLinkStatus.h"
 #include "PutByIdStatus.h"
+#include "ResolveGlobalStatus.h"
 #include <wtf/HashMap.h>
 #include <wtf/MathExtras.h>
 
@@ -94,6 +95,9 @@
     void setIntrinsicResult(bool usesResult, int resultOperand, NodeIndex);
     // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
     bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction);
+    void handleGetByOffset(
+        int destinationOperand, SpeculatedType, NodeIndex base, unsigned identifierNumber,
+        bool useInlineStorage, size_t offset);
     void handleGetById(
         int destinationOperand, SpeculatedType, NodeIndex base, unsigned identifierNumber,
         const GetByIdStatus&);
@@ -1567,6 +1571,31 @@
     }
 }
 
+void ByteCodeParser::handleGetByOffset(
+    int destinationOperand, SpeculatedType prediction, NodeIndex base, unsigned identifierNumber,
+    bool useInlineStorage, size_t offset)
+{
+    NodeIndex propertyStorage;
+    size_t offsetOffset;
+    if (useInlineStorage) {
+        propertyStorage = base;
+        ASSERT(!(sizeof(JSObject) % sizeof(EncodedJSValue)));
+        offsetOffset = sizeof(JSObject) / sizeof(EncodedJSValue);
+    } else {
+        propertyStorage = addToGraph(GetPropertyStorage, base);
+        offsetOffset = 0;
+    }
+    set(destinationOperand,
+        addToGraph(
+            GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction),
+            propertyStorage));
+        
+    StorageAccessData storageAccessData;
+    storageAccessData.offset = offset + offsetOffset;
+    storageAccessData.identifierNumber = identifierNumber;
+    m_graph.m_storageAccessData.append(storageAccessData);
+}
+
 void ByteCodeParser::handleGetById(
     int destinationOperand, SpeculatedType prediction, NodeIndex base, unsigned identifierNumber,
     const GetByIdStatus& getByIdStatus)
@@ -1620,25 +1649,9 @@
         return;
     }
     
-    NodeIndex propertyStorage;
-    size_t offsetOffset;
-    if (useInlineStorage) {
-        propertyStorage = base;
-        ASSERT(!(sizeof(JSObject) % sizeof(EncodedJSValue)));
-        offsetOffset = sizeof(JSObject) / sizeof(EncodedJSValue);
-    } else {
-        propertyStorage = addToGraph(GetPropertyStorage, base);
-        offsetOffset = 0;
-    }
-    set(destinationOperand,
-        addToGraph(
-            GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction),
-            propertyStorage));
-        
-    StorageAccessData storageAccessData;
-    storageAccessData.offset = getByIdStatus.offset() + offsetOffset;
-    storageAccessData.identifierNumber = identifierNumber;
-    m_graph.m_storageAccessData.append(storageAccessData);
+    handleGetByOffset(
+        destinationOperand, prediction, base, identifierNumber, useInlineStorage,
+        getByIdStatus.offset());
 }
 
 void ByteCodeParser::prepareToParseBlock()
@@ -2648,10 +2661,39 @@
         case op_resolve_global: {
             SpeculatedType prediction = getPrediction();
             
+            unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[
+                currentInstruction[2].u.operand];
+            
+            ResolveGlobalStatus status = ResolveGlobalStatus::computeFor(
+                m_inlineStackTop->m_profiledBlock, m_currentIndex,
+                m_codeBlock->identifier(identifierNumber));
+            if (status.isSimple()) {
+                ASSERT(status.structure());
+                
+                NodeIndex globalObject = addStructureTransitionCheck(
+                    m_inlineStackTop->m_codeBlock->globalObject(), status.structure());
+                
+                if (status.specificValue()) {
+                    ASSERT(status.specificValue().isCell());
+                    
+                    set(currentInstruction[1].u.operand,
+                        cellConstant(status.specificValue().asCell()));
+                } else {
+                    handleGetByOffset(
+                        currentInstruction[1].u.operand, prediction, globalObject,
+                        identifierNumber, status.structure()->isUsingInlineStorage(),
+                        status.offset());
+                }
+                
+                m_globalResolveNumber++; // Skip over the unused global resolve info.
+                
+                NEXT_OPCODE(op_resolve_global);
+            }
+            
             NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(prediction));
             m_graph.m_resolveGlobalData.append(ResolveGlobalData());
             ResolveGlobalData& data = ""
-            data.identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
+            data.identifierNumber = identifierNumber;
             data.resolveInfoIndex = m_globalResolveNumber++;
             set(currentInstruction[1].u.operand, resolve);
 

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (120896 => 120897)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2012-06-21 01:38:49 UTC (rev 120897)
@@ -43,6 +43,16 @@
 
 namespace JSC {
 
+JSCell* getCallableObjectSlow(JSCell* cell)
+{
+    Structure* structure = cell->structure();
+    if (structure->typeInfo().type() == JSFunctionType)
+        return cell;
+    if (structure->classInfo()->isSubClassOf(&InternalFunction::s_info))
+        return cell;
+    return 0;
+}
+
 ASSERT_CLASS_FITS_IN_CELL(JSObject);
 ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject);
 ASSERT_CLASS_FITS_IN_CELL(JSFinalObject);
@@ -133,7 +143,7 @@
         for (JSObject* obj = thisObject; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
             prototype = obj->prototype();
             if (prototype.isNull()) {
-                if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode())
+                if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getCallableObject(value)) && slot.isStrictMode())
                     throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
                 return;
             }
@@ -180,7 +190,7 @@
             break;
     }
     
-    if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode())
+    if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getCallableObject(value)) && slot.isStrictMode())
         throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
     return;
 }
@@ -196,7 +206,7 @@
 {
     ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
     PutPropertySlot slot;
-    object->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, value, attributes, slot, getJSFunction(value));
+    object->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, value, attributes, slot, getCallableObject(value));
 }
 
 bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype)
@@ -226,7 +236,7 @@
     ASSERT(value.isGetterSetter() && (attributes & Accessor));
 
     PutPropertySlot slot;
-    putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value));
+    putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getCallableObject(value));
 
     // putDirect will change our Structure if we add a new property. For
     // getters and setters, though, we also need to change our Structure

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (120896 => 120897)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2012-06-21 01:34:11 UTC (rev 120896)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2012-06-21 01:38:49 UTC (rev 120897)
@@ -46,6 +46,15 @@
         return 0;
     }
 
+    JS_EXPORT_PRIVATE JSCell* getCallableObjectSlow(JSCell*);
+
+    inline JSCell* getCallableObject(JSValue value)
+    {
+        if (!value.isCell())
+            return 0;
+        return getCallableObjectSlow(value.asCell());
+    }
+
     class GetterSetter;
     class HashEntry;
     class InternalFunction;
@@ -759,20 +768,20 @@
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
     ASSERT(!structure()->hasGetterSetterProperties());
 
-    return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value));
+    return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getCallableObject(value));
 }
 
 inline void JSObject::putDirect(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes)
 {
     ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
     PutPropertySlot slot;
-    putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value));
+    putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getCallableObject(value));
 }
 
 inline void JSObject::putDirect(JSGlobalData& globalData, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
 {
     ASSERT(!value.isGetterSetter());
-    putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getJSFunction(value));
+    putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getCallableObject(value));
 }
 
 inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes)
@@ -781,7 +790,7 @@
     PropertyStorage newStorage = propertyStorage();
     if (structure()->shouldGrowPropertyStorage())
         newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
-    size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getJSFunction(value));
+    size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getCallableObject(value));
     setPropertyStorage(globalData, newStorage, structure());
     putDirectOffset(globalData, offset, value);
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to