Title: [88280] trunk/Source/_javascript_Core
Revision
88280
Author
[email protected]
Date
2011-06-07 16:03:32 -0700 (Tue, 07 Jun 2011)

Log Message

https://bugs.webkit.org/show_bug.cgi?id=62240
DFG JIT - add support for for-loop array initialization.

Reviewed by Sam Weinig.

Support put by val beyond vector length.
Add a operationPutByValBeyondArrayBounds operation, make
PutValVal call this if the vector length check fails.

* dfg/DFGJITCodeGenerator.h:
(JSC::DFG::JITCodeGenerator::silentSpillGPR):
(JSC::DFG::JITCodeGenerator::silentFillGPR):
(JSC::DFG::JITCodeGenerator::silentSpillAllRegisters):
(JSC::DFG::JITCodeGenerator::isDoubleConstantWithInt32Value):
(JSC::DFG::JITCodeGenerator::isJSConstantWithInt32Value):
(JSC::DFG::JITCodeGenerator::isIntegerConstant):
(JSC::DFG::JITCodeGenerator::valueOfIntegerConstant):
* dfg/DFGOperations.cpp:
(JSC::DFG::operationPutByValInternal):
* dfg/DFGOperations.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (88279 => 88280)


--- trunk/Source/_javascript_Core/ChangeLog	2011-06-07 23:02:20 UTC (rev 88279)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-06-07 23:03:32 UTC (rev 88280)
@@ -1,3 +1,29 @@
+2011-06-07  Gavin Barraclough  <[email protected]>
+
+        Reviewed by Sam Weinig.
+
+        https://bugs.webkit.org/show_bug.cgi?id=62240
+        DFG JIT - add support for for-loop array initialization.
+
+        Support put by val beyond vector length.
+        Add a operationPutByValBeyondArrayBounds operation, make
+        PutValVal call this if the vector length check fails.
+
+        * dfg/DFGJITCodeGenerator.h:
+        (JSC::DFG::JITCodeGenerator::silentSpillGPR):
+        (JSC::DFG::JITCodeGenerator::silentFillGPR):
+        (JSC::DFG::JITCodeGenerator::silentSpillAllRegisters):
+        (JSC::DFG::JITCodeGenerator::isDoubleConstantWithInt32Value):
+        (JSC::DFG::JITCodeGenerator::isJSConstantWithInt32Value):
+        (JSC::DFG::JITCodeGenerator::isIntegerConstant):
+        (JSC::DFG::JITCodeGenerator::valueOfIntegerConstant):
+        * dfg/DFGOperations.cpp:
+        (JSC::DFG::operationPutByValInternal):
+        * dfg/DFGOperations.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT.h:
+
 2011-06-06  James Simonsen  <[email protected]>
 
         Reviewed by James Robinson.

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (88279 => 88280)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-06-07 23:02:20 UTC (rev 88279)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-06-07 23:03:32 UTC (rev 88280)
@@ -158,7 +158,7 @@
     // they spill all live values to the appropriate
     // slots in the RegisterFile without changing any state
     // in the GenerationInfo.
-    void silentSpillGPR(VirtualRegister spillMe, GPRReg exclude = InvalidGPRReg)
+    void silentSpillGPR(VirtualRegister spillMe, GPRReg canTrample, GPRReg exclude = InvalidGPRReg)
     {
         GenerationInfo& info = m_generationInfo[spillMe];
         ASSERT(info.registerFormat() != DataFormatNone);
@@ -170,8 +170,8 @@
         DataFormat registerFormat = info.registerFormat();
 
         if (registerFormat == DataFormatInteger) {
-            m_jit.orPtr(GPRInfo::tagTypeNumberRegister, info.gpr());
-            m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe));
+            m_jit.orPtr(GPRInfo::tagTypeNumberRegister, info.gpr(), canTrample);
+            m_jit.storePtr(canTrample, JITCompiler::addressFor(spillMe));
         } else {
             ASSERT(registerFormat & DataFormatJS || registerFormat == DataFormatCell);
             m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe));
@@ -203,8 +203,8 @@
 
         if (registerFormat == DataFormatInteger) {
             if (node.isConstant()) {
-                ASSERT(isInt32Constant(nodeIndex));
-                m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), info.gpr());
+                ASSERT(isIntegerConstant(nodeIndex));
+                m_jit.move(Imm32(valueOfIntegerConstant(nodeIndex)), info.gpr());
             } else
                 m_jit.load32(JITCompiler::addressFor(spillMe), info.gpr());
             return;
@@ -235,15 +235,21 @@
         }
     }
 
-    void silentSpillAllRegisters(GPRReg exclude, GPRReg preserve = InvalidGPRReg)
+    void silentSpillAllRegisters(GPRReg exclude, GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg)
     {
         GPRReg canTrample = GPRInfo::regT0;
-        if (preserve == GPRInfo::regT0)
+        if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0)
+            canTrample = GPRInfo::regT0;
+        else if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1)
             canTrample = GPRInfo::regT1;
+        else if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2)
+            canTrample = GPRInfo::regT2;
+        else
+            canTrample = GPRInfo::regT3;
         
         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
             if (iter.name() != InvalidVirtualRegister)
-                silentSpillGPR(iter.name(), exclude);
+                silentSpillGPR(iter.name(), canTrample, exclude);
         }
         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
             if (iter.name() != InvalidVirtualRegister)
@@ -258,7 +264,7 @@
         
         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
             if (iter.name() != InvalidVirtualRegister)
-                silentSpillGPR(iter.name());
+                silentSpillGPR(iter.name(), canTrample);
         }
         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
             if (iter.name() != InvalidVirtualRegister)
@@ -382,6 +388,56 @@
     double valueOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.valueOfDoubleConstant(nodeIndex); }
     JSValue valueOfJSConstant(NodeIndex nodeIndex) { return m_jit.valueOfJSConstant(nodeIndex); }
 
+    bool isDoubleConstantWithInt32Value(NodeIndex nodeIndex, int32_t& out)
+    {
+        if (!m_jit.isDoubleConstant(nodeIndex))
+            return false;
+        double value = m_jit.valueOfDoubleConstant(nodeIndex);
+
+        int32_t asInt32 = static_cast<int32_t>(value);
+        if (value != asInt32)
+            return false;
+        if (!asInt32 && signbit(value))
+            return false;
+
+        out = asInt32;
+        return true;
+    }
+
+    bool isJSConstantWithInt32Value(NodeIndex nodeIndex, int32_t& out)
+    {
+        if (!m_jit.isJSConstant(nodeIndex))
+            return false;
+        JSValue value = m_jit.valueOfJSConstant(nodeIndex);
+
+        if (!value.isInt32())
+            return false;
+        
+        out = value.asInt32();
+        return true;
+    }
+
+    bool isIntegerConstant(NodeIndex nodeIndex)
+    {
+        int32_t unused;
+        return isInt32Constant(nodeIndex)
+            || isDoubleConstantWithInt32Value(nodeIndex, unused)
+            || isJSConstantWithInt32Value(nodeIndex, unused);
+    }
+
+    int32_t valueOfIntegerConstant(NodeIndex nodeIndex)
+    {
+        if (isInt32Constant(nodeIndex))
+            return valueOfInt32Constant(nodeIndex);
+        int32_t result = 0;
+        bool okay = isDoubleConstantWithInt32Value(nodeIndex, result);
+        if (okay)
+            return result;
+        okay = isJSConstantWithInt32Value(nodeIndex, result);
+        ASSERT_UNUSED(okay, okay);
+        return result;
+    }
+
     Identifier* identifier(unsigned index)
     {
         return &m_jit.codeBlock()->identifier(index);

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (88279 => 88280)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-06-07 23:02:20 UTC (rev 88279)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-06-07 23:03:32 UTC (rev 88280)
@@ -56,35 +56,35 @@
     JSValue value = JSValue::decode(encodedValue);
 
     if (LIKELY(property.isUInt32())) {
-        uint32_t i = property.asUInt32();
+        uint32_t index = property.asUInt32();
 
         if (isJSArray(globalData, baseValue)) {
-            JSArray* jsArray = asArray(baseValue);
-            if (jsArray->canSetIndex(i)) {
-                jsArray->setIndex(*globalData, i, value);
+            JSArray* array = asArray(baseValue);
+            if (array->canSetIndex(index)) {
+                array->setIndex(*globalData, index, value);
                 return;
             }
 
-            jsArray->JSArray::put(exec, i, value);
+            array->JSArray::put(exec, index, value);
             return;
         }
 
-        if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
-            JSByteArray* jsByteArray = asByteArray(baseValue);
+        if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(index)) {
+            JSByteArray* byteArray = asByteArray(baseValue);
             // FIXME: the JITstub used to relink this to an optimized form!
             if (value.isInt32()) {
-                jsByteArray->setIndex(i, value.asInt32());
+                byteArray->setIndex(index, value.asInt32());
                 return;
             }
 
             double dValue = 0;
             if (value.getNumber(dValue)) {
-                jsByteArray->setIndex(i, dValue);
+                byteArray->setIndex(index, dValue);
                 return;
             }
         }
 
-        baseValue.put(exec, i, value);
+        baseValue.put(exec, index, value);
         return;
     }
 
@@ -134,21 +134,21 @@
 
         if (property.isUInt32()) {
             JSGlobalData* globalData = &exec->globalData();
-            uint32_t i = property.asUInt32();
+            uint32_t index = property.asUInt32();
 
             // FIXME: the JIT used to handle these in compiled code!
-            if (isJSArray(globalData, base) && asArray(base)->canGetIndex(i))
-                return JSValue::encode(asArray(base)->getIndex(i));
+            if (isJSArray(globalData, base) && asArray(base)->canGetIndex(index))
+                return JSValue::encode(asArray(base)->getIndex(index));
 
             // FIXME: the JITstub used to relink this to an optimized form!
-            if (isJSString(globalData, base) && asString(base)->canGetIndex(i))
-                return JSValue::encode(asString(base)->getIndex(exec, i));
+            if (isJSString(globalData, base) && asString(base)->canGetIndex(index))
+                return JSValue::encode(asString(base)->getIndex(exec, index));
 
             // FIXME: the JITstub used to relink this to an optimized form!
-            if (isJSByteArray(globalData, base) && asByteArray(base)->canAccessIndex(i))
-                return JSValue::encode(asByteArray(base)->getIndex(exec, i));
+            if (isJSByteArray(globalData, base) && asByteArray(base)->canAccessIndex(index))
+                return JSValue::encode(asByteArray(base)->getIndex(exec, index));
 
-            return JSValue::encode(baseValue.get(exec, i));
+            return JSValue::encode(baseValue.get(exec, index));
         }
 
         if (property.isString()) {
@@ -197,6 +197,13 @@
     operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
 }
 
+void operationPutByValBeyondArrayBounds(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue)
+{
+    // We should only get here if index is outside the existing vector.
+    ASSERT(!array->canSetIndex(index));
+    array->JSArray::put(exec, index, JSValue::decode(encodedValue));
+}
+
 void operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName)
 {
     PutPropertySlot slot(true);

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (88279 => 88280)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2011-06-07 23:02:20 UTC (rev 88279)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2011-06-07 23:03:32 UTC (rev 88280)
@@ -54,6 +54,7 @@
 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 operationPutByValBeyondArrayBounds(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue);
 void operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
 void operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
 void operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (88279 => 88280)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-06-07 23:02:20 UTC (rev 88279)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-06-07 23:03:32 UTC (rev 88280)
@@ -687,8 +687,18 @@
         Node& baseNode = m_jit.graph()[node.child1];
         if (baseNode.op != GetLocal || m_jit.graph().getPrediction(baseNode.local()) != PredictArray)
             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
-        speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
+        MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
 
+        // Code to handle put beyond array bounds.
+        silentSpillAllRegisters(storageReg, baseReg, propertyReg, valueReg);
+        setupStubArguments(baseReg, propertyReg, valueReg);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationPutByValBeyondArrayBounds);
+        silentFillAllRegisters(storageReg);
+        JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
+
+        withinArrayBounds.link(&m_jit);
+
         // Get the array storage.
         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
 
@@ -708,6 +718,8 @@
         // Store the value to the array.
         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
 
+        wasBeyondArrayBounds.link(&m_jit);
+
         noResult(m_compileIndex);
         break;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (88279 => 88280)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2011-06-07 23:02:20 UTC (rev 88279)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2011-06-07 23:03:32 UTC (rev 88280)
@@ -138,35 +138,6 @@
     void checkArgumentTypes();
     void initializeVariableTypes();
 
-    bool isDoubleConstantWithInt32Value(NodeIndex nodeIndex, int32_t& out)
-    {
-        if (!m_jit.isDoubleConstant(nodeIndex))
-            return false;
-        double value = m_jit.valueOfDoubleConstant(nodeIndex);
-
-        int32_t asInt32 = static_cast<int32_t>(value);
-        if (value != asInt32)
-            return false;
-        if (!asInt32 && signbit(value))
-            return false;
-
-        out = asInt32;
-        return true;
-    }
-
-    bool isJSConstantWithInt32Value(NodeIndex nodeIndex, int32_t& out)
-    {
-        if (!m_jit.isJSConstant(nodeIndex))
-            return false;
-        JSValue value = m_jit.valueOfJSConstant(nodeIndex);
-
-        if (!value.isInt32())
-            return false;
-        
-        out = value.asInt32();
-        return true;
-    }
-
     bool detectPeepHoleBranch()
     {
         // Check if the block contains precisely one more node.
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to