Title: [87431] trunk/Source/_javascript_Core
Revision
87431
Author
[email protected]
Date
2011-05-26 14:37:05 -0700 (Thu, 26 May 2011)

Log Message

https://bugs.webkit.org/show_bug.cgi?id=61508
DFG JIT - Add support for get by id self caching.

Reviewed by Geoff Garen.

Change the call out to be an unexpected call (using silent spill/fill functions),
add a structure check & compact load to the JIT code, and add repatching mechanisms.
Since DFGOperations may want to be be implemented in asm, make these symbols be extern
"C". Add an asm wrapper to pass the return address to the optimizing get-by-id operation,
so that it can look up its StructureStubInfo.

* _javascript_Core.xcodeproj/project.pbxproj:
    - Added new files.
* bytecode/StructureStubInfo.h:
    - Added 'unset' entries to union.
* dfg/DFGJITCodeGenerator.h:
(JSC::DFG::JITCodeGenerator::appendCallWithExceptionCheck):
    - Return the call, we need this to populate the StructureStubInfo.
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::compileFunction):
    - Populate the CodebBlock's StructureStubInfo Vector.
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::appendCallWithExceptionCheck):
    - Return the call, we need this to populate the StructureStubInfo.
(JSC::DFG::JITCompiler::addPropertyAccess):
(JSC::DFG::JITCompiler::PropertyAccessRecord::PropertyAccessRecord):
    - Add structures to record property access info during compilation.
* dfg/DFGOperations.cpp:
    - Made all external methods extern "C".
(JSC::DFG::operationPutByValInternal):
    - Moved outside of the extern "C" block.
* dfg/DFGOperations.h:
    - Made all external methods extern "C".
* dfg/DFGRepatch.cpp: Added.
(JSC::DFG::dfgRepatchCall):
    - repatch a call to link to a new callee function.
(JSC::DFG::dfgRepatchGetByIdSelf):
    - Modify the JIT code to optimize self accesses.
(JSC::DFG::tryCacheGetByID):
    - Internal implementation of dfgRepatchGetByID (factor out failing cases).
(JSC::DFG::dfgRepatchGetByID):
    - Used to optimize 'operationGetByIdOptimize' - repatches to 'operationGetById', and tries to optimize self accesses!
* dfg/DFGRepatch.h: Added.
    - Expose dfgRepatchGetByID.
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
    - Changed implementation of GetById ops.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (87430 => 87431)


--- trunk/Source/_javascript_Core/ChangeLog	2011-05-26 21:36:22 UTC (rev 87430)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-05-26 21:37:05 UTC (rev 87431)
@@ -1,3 +1,53 @@
+2011-05-26  Gavin Barraclough  <[email protected]>
+
+        Reviewed by Geoff Garen.
+
+        https://bugs.webkit.org/show_bug.cgi?id=61508
+        DFG JIT - Add support for get by id self caching.
+
+        Change the call out to be an unexpected call (using silent spill/fill functions),
+        add a structure check & compact load to the JIT code, and add repatching mechanisms.
+        Since DFGOperations may want to be be implemented in asm, make these symbols be extern
+        "C". Add an asm wrapper to pass the return address to the optimizing get-by-id operation,
+        so that it can look up its StructureStubInfo.
+
+        * _javascript_Core.xcodeproj/project.pbxproj:
+            - Added new files.
+        * bytecode/StructureStubInfo.h:
+            - Added 'unset' entries to union.
+        * dfg/DFGJITCodeGenerator.h:
+        (JSC::DFG::JITCodeGenerator::appendCallWithExceptionCheck):
+            - Return the call, we need this to populate the StructureStubInfo.
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::compileFunction):
+            - Populate the CodebBlock's StructureStubInfo Vector.
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::appendCallWithExceptionCheck):
+            - Return the call, we need this to populate the StructureStubInfo.
+        (JSC::DFG::JITCompiler::addPropertyAccess):
+        (JSC::DFG::JITCompiler::PropertyAccessRecord::PropertyAccessRecord):
+            - Add structures to record property access info during compilation.
+        * dfg/DFGOperations.cpp:
+            - Made all external methods extern "C".
+        (JSC::DFG::operationPutByValInternal):
+            - Moved outside of the extern "C" block.
+        * dfg/DFGOperations.h:
+            - Made all external methods extern "C".
+        * dfg/DFGRepatch.cpp: Added.
+        (JSC::DFG::dfgRepatchCall):
+            - repatch a call to link to a new callee function.
+        (JSC::DFG::dfgRepatchGetByIdSelf):
+            - Modify the JIT code to optimize self accesses.
+        (JSC::DFG::tryCacheGetByID):
+            - Internal implementation of dfgRepatchGetByID (factor out failing cases).
+        (JSC::DFG::dfgRepatchGetByID):
+            - Used to optimize 'operationGetByIdOptimize' - repatches to 'operationGetById', and tries to optimize self accesses!
+        * dfg/DFGRepatch.h: Added.
+            - Expose dfgRepatchGetByID.
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+            - Changed implementation of GetById ops.
+
 2011-05-26  Geoffrey Garen  <[email protected]>
 
         Rolled back in http://trac.webkit.org/changeset/87408 with Windows build fixed.

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (87430 => 87431)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2011-05-26 21:36:22 UTC (rev 87430)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2011-05-26 21:37:05 UTC (rev 87431)
@@ -283,6 +283,8 @@
 		86B99AB9117E391E00DF5A90 /* RopeImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AB7117E391E00DF5A90 /* RopeImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE1117E578100DF5A90 /* StringBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		86B99AE4117E578100DF5A90 /* StringImplBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE2117E578100DF5A90 /* StringImplBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		86BB09C0138E381B0056702F /* DFGRepatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86BB09BE138E381B0056702F /* DFGRepatch.cpp */; };
+		86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BB09BF138E381B0056702F /* DFGRepatch.h */; };
 		86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; };
 		86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86C568DD11A213EE0007F7F0 /* MacroAssemblerARM.cpp */; };
 		86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C568DE11A213EE0007F7F0 /* MacroAssemblerMIPS.h */; };
@@ -964,6 +966,8 @@
 		86B99AB7117E391E00DF5A90 /* RopeImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RopeImpl.h; sourceTree = "<group>"; };
 		86B99AE1117E578100DF5A90 /* StringBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringBuffer.h; path = text/StringBuffer.h; sourceTree = "<group>"; };
 		86B99AE2117E578100DF5A90 /* StringImplBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringImplBase.h; path = text/StringImplBase.h; sourceTree = "<group>"; };
+		86BB09BE138E381B0056702F /* DFGRepatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGRepatch.cpp; path = dfg/DFGRepatch.cpp; sourceTree = "<group>"; };
+		86BB09BF138E381B0056702F /* DFGRepatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGRepatch.h; path = dfg/DFGRepatch.h; sourceTree = "<group>"; };
 		86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssembler.h; sourceTree = "<group>"; };
 		86C568DD11A213EE0007F7F0 /* MacroAssemblerARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MacroAssemblerARM.cpp; sourceTree = "<group>"; };
 		86C568DE11A213EE0007F7F0 /* MacroAssemblerMIPS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerMIPS.h; sourceTree = "<group>"; };
@@ -2060,6 +2064,8 @@
 				86EC9DBF1328DF82002B2AD7 /* DFGOperations.cpp */,
 				86EC9DC01328DF82002B2AD7 /* DFGOperations.h */,
 				86EC9DC11328DF82002B2AD7 /* DFGRegisterBank.h */,
+				86BB09BE138E381B0056702F /* DFGRepatch.cpp */,
+				86BB09BF138E381B0056702F /* DFGRepatch.h */,
 				86ECA3F9132DF25A002B2AD7 /* DFGScoreBoard.h */,
 				86EC9DC21328DF82002B2AD7 /* DFGSpeculativeJIT.cpp */,
 				86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */,
@@ -2540,6 +2546,7 @@
 				7934BB7F1361979400CB99A1 /* ParallelJobsOpenMP.h in Headers */,
 				651DCA04136A6FEF00F74194 /* PassTraits.h in Headers */,
 				14F97447138C853E00DA1C67 /* HeapRootVisitor.h in Headers */,
+				86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2986,6 +2993,7 @@
 				142D6F1113539A4100B02E86 /* MarkStack.cpp in Sources */,
 				86AE64A8135E5E1C00963012 /* MacroAssemblerSH4.cpp in Sources */,
 				7934BB7C1361979400CB99A1 /* ParallelJobsGeneric.cpp in Sources */,
+				86BB09C0138E381B0056702F /* DFGRepatch.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h (87430 => 87431)


--- trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h	2011-05-26 21:36:22 UTC (rev 87430)
+++ trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h	2011-05-26 21:37:05 UTC (rev 87431)
@@ -132,6 +132,10 @@
 
         union {
             struct {
+                intptr_t deltaCheckToCall;
+                intptr_t deltaCallToLoad;
+            } unset;
+            struct {
                 WriteBarrierBase<Structure> baseObjectStructure;
             } getByIdSelf;
             struct {

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (87430 => 87431)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-05-26 21:36:22 UTC (rev 87430)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-05-26 21:37:05 UTC (rev 87431)
@@ -161,7 +161,8 @@
     void silentSpillGPR(VirtualRegister spillMe, GPRReg exclude = InvalidGPRReg)
     {
         GenerationInfo& info = m_generationInfo[spillMe];
-        ASSERT(info.registerFormat() != DataFormatNone && info.registerFormat() != DataFormatDouble);
+        ASSERT(info.registerFormat() != DataFormatNone);
+        ASSERT(info.registerFormat() != DataFormatDouble);
 
         if (!info.needsSpill() || (info.gpr() == exclude))
             return;
@@ -196,7 +197,8 @@
 
         NodeIndex nodeIndex = info.nodeIndex();
         Node& node = m_jit.graph()[nodeIndex];
-        ASSERT(info.registerFormat() != DataFormatNone && info.registerFormat() != DataFormatDouble);
+        ASSERT(info.registerFormat() != DataFormatNone);
+        ASSERT(info.registerFormat() != DataFormatDouble);
         DataFormat registerFormat = info.registerFormat();
 
         if (registerFormat == DataFormatInteger) {
@@ -793,9 +795,9 @@
         m_jit.moveDouble(FPRInfo::returnValueFPR, result);
     }
 
-    void appendCallWithExceptionCheck(const FunctionPtr& function)
+    JITCompiler::Call appendCallWithExceptionCheck(const FunctionPtr& function)
     {
-        m_jit.appendCallWithExceptionCheck(function, m_jit.graph()[m_compileIndex].exceptionInfo);
+        return m_jit.appendCallWithExceptionCheck(function, m_jit.graph()[m_compileIndex].exceptionInfo);
     }
 
     void addBranch(const MacroAssembler::Jump& jump, BlockIndex destination)

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (87430 => 87431)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2011-05-26 21:36:22 UTC (rev 87430)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2011-05-26 21:37:05 UTC (rev 87431)
@@ -282,6 +282,7 @@
     } else {
         // If compilation through the SpeculativeJIT failed, throw away the code we generated.
         m_calls.clear();
+        m_propertyAccesses.clear();
         rewindToLabel(speculativePathBegin);
 
         SpeculationCheckVector noChecks;
@@ -371,6 +372,14 @@
         }
     }
 
+    m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccesses.size());
+    for (unsigned i = 0; i < m_propertyAccesses.size(); ++i) {
+        StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
+        info.callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall);
+        info.u.unset.deltaCheckToCall = m_propertyAccesses[i].m_deltaCheckToCall;
+        info.u.unset.deltaCallToLoad = m_propertyAccesses[i].m_deltaCallToLoad;
+    }
+
     // FIXME: switch the register file check & arity check over to DFGOpertaion style calls, not JIT stubs.
     linkBuffer.link(callRegisterFileCheck, cti_register_file_check);
     linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h (87430 => 87431)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h	2011-05-26 21:36:22 UTC (rev 87430)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h	2011-05-26 21:37:05 UTC (rev 87431)
@@ -166,11 +166,12 @@
     }
 
     // Add a call out from JIT code, with an exception check.
-    void appendCallWithExceptionCheck(const FunctionPtr& function, unsigned exceptionInfo)
+    Call appendCallWithExceptionCheck(const FunctionPtr& function, unsigned exceptionInfo)
     {
         Call functionCall = call();
         Jump exceptionCheck = branchTestPtr(NonZero, AbsoluteAddress(&globalData()->exception));
         m_calls.append(CallRecord(functionCall, function, exceptionCheck, exceptionInfo));
+        return functionCall;
     }
 
     // Helper methods to check nodes for constants.
@@ -232,6 +233,11 @@
     void clearSamplingFlag(int32_t flag);
 #endif
 
+    void addPropertyAccess(JITCompiler::Call functionCall, intptr_t deltaCheckToCall, intptr_t deltaCallToLoad)
+    {
+        m_propertyAccesses.append(PropertyAccessRecord(functionCall, deltaCheckToCall, deltaCallToLoad));
+    }
+
 private:
     // These methods used in linking the speculative & non-speculative paths together.
     void fillNumericToDouble(NodeIndex, FPRReg, GPRReg temporary);
@@ -251,6 +257,21 @@
 
     // Vector of calls out from JIT code, including exception handler information.
     Vector<CallRecord> m_calls;
+
+    struct PropertyAccessRecord {
+        PropertyAccessRecord(JITCompiler::Call functionCall, intptr_t deltaCheckToCall, intptr_t deltaCallToLoad)
+            : m_functionCall(functionCall)
+            , m_deltaCheckToCall(deltaCheckToCall)
+            , m_deltaCallToLoad(deltaCallToLoad)
+        {
+        }
+
+        JITCompiler::Call m_functionCall;
+        intptr_t m_deltaCheckToCall;
+        intptr_t m_deltaCallToLoad;
+    };
+
+    Vector<PropertyAccessRecord, 4> m_propertyAccesses;
 };
 
 } } // namespace JSC::DFG

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (87430 => 87431)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-05-26 21:36:22 UTC (rev 87430)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-05-26 21:37:05 UTC (rev 87431)
@@ -29,13 +29,75 @@
 #if ENABLE(DFG_JIT)
 
 #include "CodeBlock.h"
+#include "DFGRepatch.h"
 #include "Interpreter.h"
 #include "JSByteArray.h"
 #include "JSGlobalData.h"
 #include "Operations.h"
 
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, register) \
+    asm( \
+    ".globl _" STRINGIZE(function) "\n" \
+    "_" STRINGIZE(function) ":" "\n" \
+        "mov (%rsp), %" STRINGIZE(register) "\n" \
+        "jmp _" STRINGIZE(function) "WithReturnAddress" "\n" \
+    );
+#define FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
+
 namespace JSC { namespace DFG {
 
+template<bool strict>
+ALWAYS_INLINE static void operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    JSGlobalData* globalData = &exec->globalData();
+
+    JSValue baseValue = JSValue::decode(encodedBase);
+    JSValue property = JSValue::decode(encodedProperty);
+    JSValue value = JSValue::decode(encodedValue);
+
+    if (LIKELY(property.isUInt32())) {
+        uint32_t i = property.asUInt32();
+
+        if (isJSArray(globalData, baseValue)) {
+            JSArray* jsArray = asArray(baseValue);
+            if (jsArray->canSetIndex(i)) {
+                jsArray->setIndex(*globalData, i, value);
+                return;
+            }
+
+            jsArray->JSArray::put(exec, i, value);
+            return;
+        }
+
+        if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+            JSByteArray* jsByteArray = asByteArray(baseValue);
+            // FIXME: the JITstub used to relink this to an optimized form!
+            if (value.isInt32()) {
+                jsByteArray->setIndex(i, value.asInt32());
+                return;
+            }
+
+            double dValue = 0;
+            if (value.getNumber(dValue)) {
+                jsByteArray->setIndex(i, dValue);
+                return;
+            }
+        }
+
+        baseValue.put(exec, i, value);
+        return;
+    }
+
+    // Don't put to an object if toString throws an exception.
+    Identifier ident(exec, property.toString(exec));
+    if (!globalData->exception) {
+        PutPropertySlot slot(strict);
+        baseValue.put(exec, ident, value, slot);
+    }
+}
+
+extern "C" {
+
 EncodedJSValue operationConvertThis(ExecState* exec, EncodedJSValue encodedOp)
 {
     return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec));
@@ -101,61 +163,28 @@
     return JSValue::encode(baseValue.get(exec, ident));
 }
 
-EncodedJSValue operationGetById(ExecState* exec, EncodedJSValue encodedBase, Identifier* identifier)
+EncodedJSValue operationGetById(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName)
 {
     JSValue baseValue = JSValue::decode(encodedBase);
     PropertySlot slot(baseValue);
-    return JSValue::encode(baseValue.get(exec, *identifier, slot));
+    return JSValue::encode(baseValue.get(exec, *propertyName, slot));
 }
 
-template<bool strict>
-ALWAYS_INLINE static void operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+EncodedJSValue operationGetByIdOptimizeWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr);
+FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetByIdOptimize);
+EncodedJSValue operationGetByIdOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
 {
-    JSGlobalData* globalData = &exec->globalData();
-
     JSValue baseValue = JSValue::decode(encodedBase);
-    JSValue property = JSValue::decode(encodedProperty);
-    JSValue value = JSValue::decode(encodedValue);
+    PropertySlot slot(baseValue);
+    JSValue result = baseValue.get(exec, *propertyName, slot);
 
-    if (LIKELY(property.isUInt32())) {
-        uint32_t i = property.asUInt32();
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    if (stubInfo.seen)
+        dfgRepatchGetByID(exec, baseValue, *propertyName, slot, stubInfo);
+    else
+        stubInfo.seen = true;
 
-        if (isJSArray(globalData, baseValue)) {
-            JSArray* jsArray = asArray(baseValue);
-            if (jsArray->canSetIndex(i)) {
-                jsArray->setIndex(*globalData, i, value);
-                return;
-            }
-
-            jsArray->JSArray::put(exec, i, value);
-            return;
-        }
-
-        if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
-            JSByteArray* jsByteArray = asByteArray(baseValue);
-            // FIXME: the JITstub used to relink this to an optimized form!
-            if (value.isInt32()) {
-                jsByteArray->setIndex(i, value.asInt32());
-                return;
-            }
-
-            double dValue = 0;
-            if (value.getNumber(dValue)) {
-                jsByteArray->setIndex(i, dValue);
-                return;
-            }
-        }
-
-        baseValue.put(exec, i, value);
-        return;
-    }
-
-    // Don't put to an object if toString throws an exception.
-    Identifier ident(exec, property.toString(exec));
-    if (!globalData->exception) {
-        PutPropertySlot slot(strict);
-        baseValue.put(exec, ident, value, slot);
-    }
+    return JSValue::encode(result);
 }
 
 void operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
@@ -168,28 +197,28 @@
     operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
 }
 
-void operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+void operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName)
 {
     PutPropertySlot slot(true);
-    JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot);
+    JSValue::decode(encodedBase).put(exec, *propertyName, JSValue::decode(encodedValue), slot);
 }
 
-void operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+void operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName)
 {
     PutPropertySlot slot(false);
-    JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot);
+    JSValue::decode(encodedBase).put(exec, *propertyName, JSValue::decode(encodedValue), slot);
 }
 
-void operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+void operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName)
 {
     PutPropertySlot slot(true);
-    JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot);
+    JSValue::decode(encodedBase).putDirect(exec, *propertyName, JSValue::decode(encodedValue), slot);
 }
 
-void operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+void operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName)
 {
     PutPropertySlot slot(false);
-    JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot);
+    JSValue::decode(encodedBase).putDirect(exec, *propertyName, JSValue::decode(encodedValue), slot);
 }
 
 bool operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
@@ -240,6 +269,7 @@
     return JSValue::decode(encodedOp).toBoolean(exec);
 }
 
+} // extern "C"
 } } // namespace JSC::DFG
 
 #endif

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (87430 => 87431)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2011-05-26 21:36:22 UTC (rev 87430)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2011-05-26 21:37:05 UTC (rev 87431)
@@ -30,12 +30,9 @@
 
 #include <dfg/DFGJITCompiler.h>
 
-namespace JSC {
+namespace JSC { namespace DFG {
+extern "C" {
 
-class Identifier;
-
-namespace DFG {
-
 // These typedefs provide typechecking when generating calls out to helper routines;
 // this helps prevent calling a helper routine with the wrong arguments!
 typedef EncodedJSValue (*J_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
@@ -54,6 +51,7 @@
 EncodedJSValue operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
 EncodedJSValue operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty);
 EncodedJSValue operationGetById(ExecState*, EncodedJSValue encodedBase, Identifier*);
+EncodedJSValue operationGetByIdOptimize(ExecState*, EncodedJSValue encodedBase, Identifier*);
 void operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
 void operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
 void operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
@@ -84,6 +82,7 @@
 int32_t dfgConvertJSValueToInt32(ExecState*, EncodedJSValue);
 bool dfgConvertJSValueToBoolean(ExecState*, EncodedJSValue);
 
+} // extern "C"
 } } // namespace JSC::DFG
 
 #endif

Added: trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp (0 => 87431)


--- trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2011-05-26 21:37:05 UTC (rev 87431)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 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 "DFGRepatch.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGOperations.h"
+#include "RepatchBuffer.h"
+
+namespace JSC { namespace DFG {
+
+static void dfgRepatchCall(CodeBlock* codeblock, CodeLocationCall call, FunctionPtr newCalleeFunction)
+{
+    RepatchBuffer repatchBuffer(codeblock);
+    repatchBuffer.relink(call, newCalleeFunction);
+}
+
+static void dfgRepatchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure, size_t offset)
+{
+    RepatchBuffer repatchBuffer(codeBlock);
+
+    // Only optimize once!
+    repatchBuffer.relink(stubInfo.callReturnLocation, operationGetById);
+
+    // Patch the structure check & the offset of the load.
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(intptr_t)stubInfo.u.unset.deltaCheckToCall), structure);
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.u.unset.deltaCallToLoad), sizeof(JSValue) * offset);
+}
+
+static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier&, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+    // FIXME: Write a test that proves we need to check for recursion here just
+    // like the interpreter does, then add a check for recursion.
+
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSGlobalData* globalData = &exec->globalData();
+
+    // FIXME: should support length access for Array & String.
+
+    // FIXME: Cache property access for immediates.
+    if (!baseValue.isCell())
+        return false;
+    JSCell* baseCell = baseValue.asCell();
+    Structure* structure = baseCell->structure();
+    if (!slot.isCacheable())
+        return false;
+    if (structure->isUncacheableDictionary())
+        return false;
+
+    // Optimize self access.
+    if (slot.slotBase() == baseValue) {
+        if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset))
+            return false;
+
+        dfgRepatchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset());
+        stubInfo.initGetByIdSelf(*globalData, codeBlock->ownerExecutable(), structure);
+        return true;
+    }
+
+    // FIXME: should support prototype & chain accesses!
+    return false;
+}
+
+void dfgRepatchGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+    bool cached = tryCacheGetByID(exec, baseValue, propertyName, slot, stubInfo);
+    if (!cached)
+        dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
+}
+
+} } // namespace JSC::DFG
+
+#endif

Added: trunk/Source/_javascript_Core/dfg/DFGRepatch.h (0 => 87431)


--- trunk/Source/_javascript_Core/dfg/DFGRepatch.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.h	2011-05-26 21:37:05 UTC (rev 87431)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 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 DFGRepatch_h
+#define DFGRepatch_h
+
+#if ENABLE(DFG_JIT)
+
+#include <dfg/DFGJITCompiler.h>
+
+namespace JSC { namespace DFG {
+
+void dfgRepatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
+
+} } // namespace JSC::DFG
+
+#endif
+#endif

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (87430 => 87431)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-05-26 21:36:22 UTC (rev 87430)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-05-26 21:37:05 UTC (rev 87431)
@@ -185,9 +185,9 @@
         GPRReg gpr = allocate();
 
         if (node.isConstant()) {
-            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
             JSValue jsValue = constantAsJSValue(nodeIndex);
             if (jsValue.isCell()) {
+                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
                 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
                 info.fillJSValue(gpr, DataFormatJSCell);
                 return gpr;
@@ -805,13 +805,37 @@
     }
 
     case GetById: {
-        JSValueOperand base(this, node.child1);
+        SpeculateCellOperand base(this, node.child1);
+        GPRTemporary result(this, base);
+
         GPRReg baseGPR = base.gpr();
-        flushRegisters();
+        GPRReg resultGPR = result.gpr();
 
-        GPRResult result(this);
-        callOperation(operationGetById, result.gpr(), baseGPR, identifier(node.identifierNumber()));
-        jsValueResult(result.gpr(), m_compileIndex);
+        JITCompiler::DataLabelPtr structureToCompare;
+        JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::Equal, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
+
+        silentSpillAllRegisters(resultGPR, baseGPR);
+        m_jit.move(baseGPR, GPRInfo::argumentGPR1);
+        m_jit.move(JITCompiler::ImmPtr(identifier(node.identifierNumber())), GPRInfo::argumentGPR2);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationGetByIdOptimize);
+        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
+        silentFillAllRegisters(resultGPR);
+
+        JITCompiler::Jump handledByC = m_jit.jump();
+        structureCheck.link(&m_jit);
+
+        m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
+        JITCompiler::DataLabelCompact loadWithPatch = m_jit.loadPtrWithCompactAddressOffsetPatch(JITCompiler::Address(resultGPR, 0), resultGPR);
+
+        intptr_t checkToCall = m_jit.differenceBetween(structureToCompare, functionCall);
+        intptr_t callToLoad = m_jit.differenceBetween(functionCall, loadWithPatch);
+
+        handledByC.link(&m_jit);
+
+        m_jit.addPropertyAccess(functionCall, checkToCall, callToLoad);
+
+        jsValueResult(resultGPR, m_compileIndex);
         break;
     }
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to