DFG JIT cannot compile op_new_object, op_new_array,
[WebKit.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
index 23088a8..5409dd6 100644 (file)
@@ -685,6 +685,36 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
     return false;
 }
 
+template<typename T>
+void SpeculativeJIT::emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
+{
+    MarkedSpace::SizeClass* sizeClass = &m_jit.globalData()->heap.sizeClassForObject(sizeof(JSFinalObject));
+    
+    m_jit.loadPtr(&sizeClass->firstFreeCell, resultGPR);
+    slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
+    
+    // The object is half-allocated: we have what we know is a fresh object, but
+    // it's still on the GC's free list.
+    
+    // Ditch the structure by placing it into the structure slot, so that we can reuse
+    // scratchGPR.
+    m_jit.storePtr(structure, MacroAssembler::Address(resultGPR, JSObject::structureOffset()));
+    
+    // Now that we have scratchGPR back, remove the object from the free list
+    m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
+    m_jit.storePtr(scratchGPR, &sizeClass->firstFreeCell);
+    
+    // Initialize the object's vtable
+    m_jit.storePtr(MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr), MacroAssembler::Address(resultGPR));
+    
+    // Initialize the object's inheritorID.
+    m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
+    
+    // Initialize the object's property storage pointer.
+    m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR);
+    m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, JSFinalObject::offsetOfPropertyStorage()));
+}
+
 void SpeculativeJIT::compile(Node& node)
 {
     NodeType op = node.op;
@@ -1386,8 +1416,7 @@ void SpeculativeJIT::compile(Node& node)
 
         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
         // If we have predicted the base to be type array, we can skip the check.
-        Node& baseNode = m_jit.graph()[node.child1()];
-        if (baseNode.op != GetLocal || !isArrayPrediction(m_jit.graph().getPrediction(baseNode.local())))
+        if (!isKnownArray(node.child1()))
             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())));
 
@@ -1421,8 +1450,7 @@ void SpeculativeJIT::compile(Node& node)
 
         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
         // If we have predicted the base to be type array, we can skip the check.
-        Node& baseNode = m_jit.graph()[node.child1()];
-        if (baseNode.op != GetLocal || !isArrayPrediction(m_jit.graph().getPrediction(baseNode.local())))
+        if (!isKnownArray(node.child1()))
             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
 
         base.use();
@@ -1637,9 +1665,10 @@ void SpeculativeJIT::compile(Node& node)
         break;
     }
         
-    case StrCat: {
-        // We really don't want to grow the register file just to do a StrCat. Say we
-        // have 50 functions on the stack that all have a StrCat in them that has
+    case StrCat:
+    case NewArray: {
+        // We really don't want to grow the register file just to do a StrCat or NewArray.
+        // Say we have 50 functions on the stack that all have a StrCat in them that has
         // upwards of 10 operands. In the DFG this would mean that each one gets
         // some random virtual register, and then to do the StrCat we'd need a second
         // span of 10 operands just to have somewhere to copy the 10 operands to, where
@@ -1669,12 +1698,32 @@ void SpeculativeJIT::compile(Node& node)
         
         GPRResult result(this);
         
-        callOperation(operationStrCat, result.gpr(), buffer, node.numChildren());
+        callOperation(op == StrCat ? operationStrCat : operationNewArray, result.gpr(), buffer, node.numChildren());
         
-        jsValueResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
+        cellResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
         break;
     }
-
+        
+    case NewArrayBuffer: {
+        flushRegisters();
+        GPRResult result(this);
+        
+        callOperation(operationNewArrayBuffer, result.gpr(), node.startConstant(), node.numConstants());
+        
+        cellResult(result.gpr(), m_compileIndex);
+        break;
+    }
+        
+    case NewRegexp: {
+        flushRegisters();
+        GPRResult result(this);
+        
+        callOperation(operationNewRegexp, result.gpr(), m_jit.codeBlock()->regexp(node.regexpIndex()));
+        
+        cellResult(result.gpr(), m_compileIndex);
+        break;
+    }
+        
     case ConvertThis: {
         SpeculateCellOperand thisValue(this, node.child1());
 
@@ -1718,46 +1767,49 @@ void SpeculativeJIT::compile(Node& node)
         m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
         slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
         
-        MarkedSpace::SizeClass* sizeClass = &m_jit.globalData()->heap.sizeClassForObject(sizeof(JSFinalObject));
+        emitAllocateJSFinalObject(scratchGPR, resultGPR, scratchGPR, slowPath);
         
-        m_jit.loadPtr(&sizeClass->firstFreeCell, resultGPR);
-        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
+        MacroAssembler::Jump done = m_jit.jump();
         
-        // The object is half-allocated: we have what we know is a fresh object, but
-        // it's still on the GC's free list.
+        slowPath.link(&m_jit);
         
-        // Ditch the inheritorID by placing it into the structure, so that we can reuse
-        // scratchGPR.
-        m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, JSObject::structureOffset()));
+        silentSpillAllRegisters(resultGPR);
+        m_jit.move(protoGPR, GPRInfo::argumentGPR1);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        appendCallWithExceptionCheck(operationCreateThis);
+        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
+        silentFillAllRegisters(resultGPR);
         
-        // Now that we have scratchGPR back, remove the object from the free list
-        m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
-        m_jit.storePtr(scratchGPR, &sizeClass->firstFreeCell);
+        done.link(&m_jit);
         
-        // Initialize the object's vtable
-        m_jit.storePtr(MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr), MacroAssembler::Address(resultGPR));
+        cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+        
+    case NewObject: {
+        GPRTemporary result(this);
+        GPRTemporary scratch(this);
+        
+        GPRReg resultGPR = result.gpr();
+        GPRReg scratchGPR = scratch.gpr();
         
-        // Initialize the object's inheritorID.
-        m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
+        MacroAssembler::JumpList slowPath;
         
-        // Initialize the object's property storage pointer.
-        m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR);
-        m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, JSFinalObject::offsetOfPropertyStorage()));
+        emitAllocateJSFinalObject(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()->emptyObjectStructure()), resultGPR, scratchGPR, slowPath);
         
         MacroAssembler::Jump done = m_jit.jump();
         
         slowPath.link(&m_jit);
         
         silentSpillAllRegisters(resultGPR);
-        m_jit.move(protoGPR, GPRInfo::argumentGPR1);
         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
-        appendCallWithExceptionCheck(operationCreateThis);
+        appendCallWithExceptionCheck(operationNewObject);
         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
         silentFillAllRegisters(resultGPR);
         
         done.link(&m_jit);
         
-        cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+        cellResult(resultGPR, m_compileIndex);
         break;
     }
         
@@ -1833,14 +1885,13 @@ void SpeculativeJIT::compile(Node& node)
     }
         
     case GetArrayLength: {
-        Node& baseNode = m_jit.graph()[node.child1()];
         SpeculateCellOperand base(this, node.child1());
         GPRTemporary result(this);
         
         GPRReg baseGPR = base.gpr();
         GPRReg resultGPR = result.gpr();
         
-        if (baseNode.op != GetLocal || !isArrayPrediction(m_jit.graph().getPrediction(baseNode.local())))
+        if (!isKnownArray(node.child1()))
             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
         
         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);