X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/93a3786624b2768d89bfa27e46598dc64e2fb70a..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/dfg/DFGVariableEventStream.cpp diff --git a/dfg/DFGVariableEventStream.cpp b/dfg/DFGVariableEventStream.cpp index a3f2ac6..e3f413c 100644 --- a/dfg/DFGVariableEventStream.cpp +++ b/dfg/DFGVariableEventStream.cpp @@ -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 #include @@ -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& 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(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 operandSources(codeBlock->numParameters(), numVariables); + for (unsigned i = operandSources.size(); i--;) + operandSources[i] = ValueSource(SourceIsDead); HashMap 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::iterator iter = generationInfos.begin(); - HashMap::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(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