]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGVariableEventStream.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGVariableEventStream.cpp
index a3f2ac6ff7f1770665cd55aff86a78f9194454e2..e3f413c3b8ff2ff6a10250333ea40ca28879faf8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,8 +29,9 @@
 #if ENABLE(DFG_JIT)
 
 #include "CodeBlock.h"
+#include "DFGJITCode.h"
 #include "DFGValueSource.h"
-#include "Operations.h"
+#include "JSCInlines.h"
 #include <wtf/DataLog.h>
 #include <wtf/HashMap.h>
 
@@ -47,11 +48,14 @@ namespace {
 
 struct MinifiedGenerationInfo {
     bool filled; // true -> in gpr/fpr/pair, false -> spilled
+    bool alive;
     VariableRepresentation u;
     DataFormat format;
     
     MinifiedGenerationInfo()
-        : format(DataFormatNone)
+        : filled(false)
+        , alive(false)
+        , format(DataFormatNone)
     {
     }
     
@@ -61,13 +65,19 @@ struct MinifiedGenerationInfo {
         case BirthToFill:
         case Fill:
             filled = true;
+            alive = true;
             break;
         case BirthToSpill:
         case Spill:
             filled = false;
+            alive = true;
             break;
+        case Birth:
+            alive = true;
+            return;
         case Death:
             format = DataFormatNone;
+            alive = false;
             return;
         default:
             return;
@@ -80,25 +90,23 @@ struct MinifiedGenerationInfo {
 
 } // namespace
 
-bool VariableEventStream::tryToSetConstantRecovery(ValueRecovery& recovery, CodeBlock* codeBlock, MinifiedNode* node) const
+bool VariableEventStream::tryToSetConstantRecovery(ValueRecovery& recovery, MinifiedNode* node) const
 {
     if (!node)
         return false;
     
-    if (node->hasConstantNumber()) {
-        recovery = ValueRecovery::constant(
-            codeBlock->constantRegister(
-                FirstConstantRegisterIndex + node->constantNumber()).get());
+    if (node->hasConstant()) {
+        recovery = ValueRecovery::constant(node->constant());
         return true;
     }
     
-    if (node->hasWeakConstant()) {
-        recovery = ValueRecovery::constant(node->weakConstant());
+    if (node->op() == PhantomDirectArguments) {
+        recovery = ValueRecovery::directArgumentsThatWereNotCreated(node->id());
         return true;
     }
     
-    if (node->op() == PhantomArguments) {
-        recovery = ValueRecovery::argumentsThatWereNotCreated();
+    if (node->op() == PhantomClonedArguments) {
+        recovery = ValueRecovery::outOfBandArgumentsThatWereNotCreated(node->id());
         return true;
     }
     
@@ -109,12 +117,12 @@ void VariableEventStream::reconstruct(
     CodeBlock* codeBlock, CodeOrigin codeOrigin, MinifiedGraph& graph,
     unsigned index, Operands<ValueRecovery>& valueRecoveries) const
 {
-    ASSERT(codeBlock->getJITType() == JITCode::DFGJIT);
+    ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
     CodeBlock* baselineCodeBlock = codeBlock->baselineVersion();
     
     unsigned numVariables;
     if (codeOrigin.inlineCallFrame)
-        numVariables = baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame)->m_numCalleeRegisters + codeOrigin.inlineCallFrame->stackOffset;
+        numVariables = baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame)->m_numCalleeRegisters + VirtualRegister(codeOrigin.inlineCallFrame->stackOffset).toLocal() + 1;
     else
         numVariables = baselineCodeBlock->m_numCalleeRegisters;
     
@@ -123,8 +131,10 @@ void VariableEventStream::reconstruct(
     // reflect this.
     if (!index) {
         valueRecoveries = Operands<ValueRecovery>(codeBlock->numParameters(), numVariables);
-        for (size_t i = 0; i < valueRecoveries.size(); ++i)
-            valueRecoveries[i] = ValueRecovery::alreadyInJSStack();
+        for (size_t i = 0; i < valueRecoveries.size(); ++i) {
+            valueRecoveries[i] = ValueRecovery::displacedInJSStack(
+                VirtualRegister(valueRecoveries.operandForIndex(i)), DataFormatJS);
+        }
         return;
     }
     
@@ -133,12 +143,10 @@ void VariableEventStream::reconstruct(
     while (at(startIndex).kind() != Reset)
         startIndex--;
     
-#if DFG_ENABLE(DEBUG_VERBOSE)
-    dataLogF("Computing OSR exit recoveries starting at seq#%u.\n", startIndex);
-#endif
-
     // Step 2: Create a mock-up of the DFG's state and execute the events.
     Operands<ValueSource> operandSources(codeBlock->numParameters(), numVariables);
+    for (unsigned i = operandSources.size(); i--;)
+        operandSources[i] = ValueSource(SourceIsDead);
     HashMap<MinifiedID, MinifiedGenerationInfo> generationInfos;
     for (unsigned i = startIndex; i < index; ++i) {
         const VariableEvent& event = at(i);
@@ -147,7 +155,8 @@ void VariableEventStream::reconstruct(
             // nothing to do.
             break;
         case BirthToFill:
-        case BirthToSpill: {
+        case BirthToSpill:
+        case Birth: {
             MinifiedGenerationInfo info;
             info.update(event);
             generationInfos.add(event.id(), info);
@@ -162,12 +171,12 @@ void VariableEventStream::reconstruct(
             break;
         }
         case MovHintEvent:
-            if (operandSources.hasOperand(event.operand()))
-                operandSources.setOperand(event.operand(), ValueSource(event.id()));
+            if (operandSources.hasOperand(event.bytecodeRegister()))
+                operandSources.setOperand(event.bytecodeRegister(), ValueSource(event.id()));
             break;
         case SetLocalEvent:
-            if (operandSources.hasOperand(event.operand()))
-                operandSources.setOperand(event.operand(), ValueSource::forDataFormat(event.dataFormat()));
+            if (operandSources.hasOperand(event.bytecodeRegister()))
+                operandSources.setOperand(event.bytecodeRegister(), ValueSource::forDataFormat(event.machineRegister(), event.dataFormat()));
             break;
         default:
             RELEASE_ASSERT_NOT_REACHED();
@@ -186,102 +195,14 @@ void VariableEventStream::reconstruct(
         
         ASSERT(source.kind() == HaveNode);
         MinifiedNode* node = graph.at(source.id());
-        if (tryToSetConstantRecovery(valueRecoveries[i], codeBlock, node))
-            continue;
-        
         MinifiedGenerationInfo info = generationInfos.get(source.id());
-        if (info.format == DataFormatNone) {
-            // Try to see if there is an alternate node that would contain the value we want.
-            // There are four possibilities:
-            //
-            // Int32ToDouble: We can use this in place of the original node, but
-            //    we'd rather not; so we use it only if it is the only remaining
-            //    live version.
-            //
-            // ValueToInt32: If the only remaining live version of the value is
-            //    ValueToInt32, then we can use it.
-            //
-            // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
-            //    then the only remaining uses are ones that want a properly formed number
-            //    rather than a UInt32 intermediate.
-            //
-            // DoubleAsInt32: Same as UInt32ToNumber.
-            //
-            // The reverse of the above: This node could be a UInt32ToNumber, but its
-            //    alternative is still alive. This means that the only remaining uses of
-            //    the number would be fine with a UInt32 intermediate.
-            
-            bool found = false;
-            
-            if (node && node->op() == UInt32ToNumber) {
-                MinifiedID id = node->child1();
-                if (tryToSetConstantRecovery(valueRecoveries[i], codeBlock, graph.at(id)))
-                    continue;
-                info = generationInfos.get(id);
-                if (info.format != DataFormatNone)
-                    found = true;
-            }
-            
-            if (!found) {
-                MinifiedID int32ToDoubleID;
-                MinifiedID valueToInt32ID;
-                MinifiedID uint32ToNumberID;
-                MinifiedID doubleAsInt32ID;
-                
-                HashMap<MinifiedID, MinifiedGenerationInfo>::iterator iter = generationInfos.begin();
-                HashMap<MinifiedID, MinifiedGenerationInfo>::iterator end = generationInfos.end();
-                for (; iter != end; ++iter) {
-                    MinifiedID id = iter->key;
-                    node = graph.at(id);
-                    if (!node)
-                        continue;
-                    if (!node->hasChild1())
-                        continue;
-                    if (node->child1() != source.id())
-                        continue;
-                    if (iter->value.format == DataFormatNone)
-                        continue;
-                    switch (node->op()) {
-                    case Int32ToDouble:
-                    case ForwardInt32ToDouble:
-                        int32ToDoubleID = id;
-                        break;
-                    case ValueToInt32:
-                        valueToInt32ID = id;
-                        break;
-                    case UInt32ToNumber:
-                        uint32ToNumberID = id;
-                        break;
-                    case DoubleAsInt32:
-                        doubleAsInt32ID = id;
-                        break;
-                    default:
-                        break;
-                    }
-                }
-                
-                MinifiedID idToUse;
-                if (!!doubleAsInt32ID)
-                    idToUse = doubleAsInt32ID;
-                else if (!!int32ToDoubleID)
-                    idToUse = int32ToDoubleID;
-                else if (!!valueToInt32ID)
-                    idToUse = valueToInt32ID;
-                else if (!!uint32ToNumberID)
-                    idToUse = uint32ToNumberID;
-                
-                if (!!idToUse) {
-                    info = generationInfos.get(idToUse);
-                    ASSERT(info.format != DataFormatNone);
-                    found = true;
-                }
-            }
-            
-            if (!found) {
-                valueRecoveries[i] = ValueRecovery::constant(jsUndefined());
-                continue;
-            }
+        if (!info.alive) {
+            valueRecoveries[i] = ValueRecovery::constant(jsUndefined());
+            continue;
         }
+
+        if (tryToSetConstantRecovery(valueRecoveries[i], node))
+            continue;
         
         ASSERT(info.format != DataFormatNone);
         
@@ -303,13 +224,6 @@ void VariableEventStream::reconstruct(
         valueRecoveries[i] =
             ValueRecovery::displacedInJSStack(static_cast<VirtualRegister>(info.u.virtualReg), info.format);
     }
-    
-    // Step 4: Make sure that for locals that coincide with true call frame headers, the exit compiler knows
-    // that those values don't have to be recovered. Signal this by using ValueRecovery::alreadyInJSStack()
-    for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->caller.inlineCallFrame) {
-        for (unsigned i = JSStack::CallFrameHeaderSize; i--;)
-            valueRecoveries.setLocal(inlineCallFrame->stackOffset - i - 1, ValueRecovery::alreadyInJSStack());
-    }
 }
 
 } } // namespace JSC::DFG