Refactor build deopt frame state

use dfs order build frame state

issue: I5VVZQ
Signed-off-by: sunzhe23 <sunzhe23@huawei.com>
This commit is contained in:
sunzhe23 2022-10-15 12:09:38 +08:00
parent b3f51ddf4c
commit 5c51bf4087
22 changed files with 384 additions and 297 deletions

View File

@ -63,13 +63,13 @@ size_t ArgumentAccessor::GetFunctionArgIndex(const size_t currentVreg, const boo
return static_cast<size_t>(CommonArgIdx::NEW_TARGET);
}
if (!haveFunc && currentVreg == 1) {
return static_cast<size_t>(CommonArgIdx::THIS);
return static_cast<size_t>(CommonArgIdx::THIS_OBJECT);
}
if (!haveNewTarget && currentVreg == 0) {
return static_cast<size_t>(CommonArgIdx::FUNC);
}
if (!haveNewTarget && currentVreg == 1) {
return static_cast<size_t>(CommonArgIdx::THIS);
return static_cast<size_t>(CommonArgIdx::THIS_OBJECT);
}
if (!haveThis && currentVreg == 0) {
return static_cast<size_t>(CommonArgIdx::FUNC);
@ -87,7 +87,7 @@ size_t ArgumentAccessor::GetFunctionArgIndex(const size_t currentVreg, const boo
return static_cast<size_t>(CommonArgIdx::NEW_TARGET);
}
if (haveThis) {
return static_cast<size_t>(CommonArgIdx::THIS);
return static_cast<size_t>(CommonArgIdx::THIS_OBJECT);
}
}
return currentVreg - numCommonArgs + static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS);

View File

@ -29,7 +29,7 @@ enum class CommonArgIdx : uint8_t {
ACTUAL_ARGC,
FUNC,
NEW_TARGET,
THIS,
THIS_OBJECT,
NUM_OF_ARGS,
};

View File

@ -385,8 +385,10 @@ void BytecodeCircuitBuilder::BuildBasicBlocks(std::map<std::pair<uint8_t *, uint
void BytecodeCircuitBuilder::ComputeDominatorTree()
{
// Construct graph backward order
std::map<size_t, size_t> bbIdToDfsTimestamp;
std::unordered_map<size_t, size_t> dfsFatherIdx;
std::unordered_map<size_t, size_t> bbDfsTimestampToIdx;
std::vector<size_t> basicBlockList;
size_t timestamp = 0;
std::deque<size_t> pendingList;
std::vector<size_t> visited(graph_.size(), 0);
@ -396,30 +398,30 @@ void BytecodeCircuitBuilder::ComputeDominatorTree()
while (!pendingList.empty()) {
size_t curBlockId = pendingList.back();
pendingList.pop_back();
bbDfsList_.push_back(curBlockId);
bbIdToDfsTimestamp_[curBlockId] = timestamp++;
basicBlockList.push_back(curBlockId);
bbIdToDfsTimestamp[curBlockId] = timestamp++;
for (const auto &succBlock: graph_[curBlockId].succs) {
if (visited[succBlock->id] == 0) {
visited[succBlock->id] = 1;
pendingList.push_back(succBlock->id);
dfsFatherIdx[succBlock->id] = bbIdToDfsTimestamp_[curBlockId];
dfsFatherIdx[succBlock->id] = bbIdToDfsTimestamp[curBlockId];
}
}
}
for (size_t idx = 0; idx < bbDfsList_.size(); idx++) {
bbDfsTimestampToIdx[bbDfsList_[idx]] = idx;
for (size_t idx = 0; idx < basicBlockList.size(); idx++) {
bbDfsTimestampToIdx[basicBlockList[idx]] = idx;
}
RemoveDeadRegions();
RemoveDeadRegions(bbIdToDfsTimestamp);
std::vector<size_t> immDom(bbDfsList_.size()); // immediate dominator with dfs order index
std::vector<size_t> semiDom(bbDfsList_.size());
std::vector<size_t> immDom(basicBlockList.size()); // immediate dominator with dfs order index
std::vector<size_t> semiDom(basicBlockList.size());
std::vector<size_t> realImmDom(graph_.size()); // immediate dominator with real index
std::vector<std::vector<size_t> > semiDomTree(bbDfsList_.size());
std::vector<std::vector<size_t> > semiDomTree(basicBlockList.size());
{
std::vector<size_t> parent(bbDfsList_.size());
std::vector<size_t> parent(basicBlockList.size());
std::iota(parent.begin(), parent.end(), 0);
std::vector<size_t> minIdx(bbDfsList_.size());
std::vector<size_t> minIdx(basicBlockList.size());
std::function<size_t(size_t)> unionFind = [&] (size_t idx) -> size_t {
if (parent[idx] == idx) return idx;
size_t unionFindSetRoot = unionFind(parent[idx]);
@ -435,8 +437,8 @@ void BytecodeCircuitBuilder::ComputeDominatorTree()
};
std::iota(semiDom.begin(), semiDom.end(), 0);
semiDom[0] = semiDom.size();
for (size_t idx = bbDfsList_.size() - 1; idx >= 1; idx--) {
for (const auto &preBlock : graph_[bbDfsList_[idx]].preds) {
for (size_t idx = basicBlockList.size() - 1; idx >= 1; idx--) {
for (const auto &preBlock : graph_[basicBlockList[idx]].preds) {
if (bbDfsTimestampToIdx[preBlock->id] < idx) {
semiDom[idx] = std::min(semiDom[idx], bbDfsTimestampToIdx[preBlock->id]);
} else {
@ -453,14 +455,14 @@ void BytecodeCircuitBuilder::ComputeDominatorTree()
}
}
minIdx[idx] = idx;
merge(dfsFatherIdx[bbDfsList_[idx]], idx);
merge(dfsFatherIdx[basicBlockList[idx]], idx);
semiDomTree[semiDom[idx]].push_back(idx);
}
for (size_t idx = 1; idx < bbDfsList_.size(); idx++) {
for (size_t idx = 1; idx < basicBlockList.size(); idx++) {
if (immDom[idx] != semiDom[idx]) {
immDom[idx] = immDom[immDom[idx]];
}
realImmDom[bbDfsList_[idx]] = bbDfsList_[immDom[idx]];
realImmDom[basicBlockList[idx]] = basicBlockList[immDom[idx]];
}
semiDom[0] = 0;
}
@ -525,12 +527,12 @@ void BytecodeCircuitBuilder::ComputeDomFrontiers(const std::vector<size_t> &immD
}
}
void BytecodeCircuitBuilder::RemoveDeadRegions()
void BytecodeCircuitBuilder::RemoveDeadRegions(const std::map<size_t, size_t> &bbIdToDfsTimestamp)
{
for (auto &block: graph_) {
std::vector<BytecodeRegion *> newPreds;
for (auto &bb : block.preds) {
if (bbIdToDfsTimestamp_.count(bb->id)) {
if (bbIdToDfsTimestamp.count(bb->id)) {
newPreds.emplace_back(bb);
}
}
@ -538,7 +540,7 @@ void BytecodeCircuitBuilder::RemoveDeadRegions()
}
for (auto &block : graph_) {
block.isDead = !bbIdToDfsTimestamp_.count(block.id);
block.isDead = !bbIdToDfsTimestamp.count(block.id);
if (block.isDead) {
block.succs.clear();
}
@ -1743,7 +1745,6 @@ void BytecodeCircuitBuilder::BuildCircuitArgs()
argAcc_.CollectArgs();
if (hasTypes_) {
argAcc_.FillArgsGateType(&typeRecorder_);
frameStateBuilder_.BuildArgsValues(&argAcc_);
}
}
@ -1998,7 +1999,7 @@ GateRef BytecodeCircuitBuilder::NewConst(const BytecodeInfo &info)
gate = argAcc_.GetCommonArgGate(CommonArgIdx::NEW_TARGET);
break;
case EcmaOpcode::LDTHIS:
gate = argAcc_.GetCommonArgGate(CommonArgIdx::THIS);
gate = argAcc_.GetCommonArgGate(CommonArgIdx::THIS_OBJECT);
break;
default:
UNREACHABLE();
@ -2360,56 +2361,125 @@ GateRef BytecodeCircuitBuilder::RenameVariable(const size_t bbId, const uint8_t
}
}
void BytecodeCircuitBuilder::BuildDfsList()
{
bbDfsList_.clear();
std::deque<size_t> pendingList;
std::vector<bool> visited(graph_.size(), false);
auto basicBlockId = graph_[0].id;
pendingList.push_back(basicBlockId);
while (!pendingList.empty()) {
size_t curBlockId = pendingList.back();
if (visited[curBlockId]) {
bbDfsList_.push_back(curBlockId);
pendingList.pop_back();
continue;
}
visited[curBlockId] = true;
for (const auto &succBlock: graph_[curBlockId].succs) {
if (!visited[succBlock->id]) {
pendingList.push_back(succBlock->id);
}
}
for (const auto &succBlock: graph_[curBlockId].catchs) {
if (!visited[succBlock->id]) {
pendingList.push_back(succBlock->id);
}
}
}
}
void BytecodeCircuitBuilder::FrameStateReplacePhi(GateRef phi, size_t reg)
{
ASSERT(gateAcc_.GetOpCode(phi) == OpCode::VALUE_SELECTOR);
auto numValue = gateAcc_.GetNumValueIn(phi);
for (size_t i = 0; i < numValue; i++) {
auto value = gateAcc_.GetValueIn(phi, i);
auto it = jsgateToBytecode_.find(value);
if (it == jsgateToBytecode_.cend()) {
continue;
}
auto id = jsgateToBytecode_.at(value).first;
frameStateBuilder_.AdvenceToBasicBlock(id);
frameStateBuilder_.UpdateVirtualRegister(reg, value);
}
}
void BytecodeCircuitBuilder::BuildFrameState()
{
const uint8_t *predPc = nullptr;
BuildDfsList();
auto undefinedGate = circuit_.GetConstantGate(MachineType::I64,
JSTaggedValue::VALUE_UNDEFINED,
GateType::TaggedValue());
for (auto &dfsOrder : bbDfsList_) {
auto bb = graph_[dfsOrder];
if (bb.isDead) {
continue;
}
if (bb.preds.size() != 0) {
std::sort(bb.preds.begin(), bb.preds.end(), [this](BytecodeRegion *a, BytecodeRegion *b) {
return bbIdToDfsTimestamp_[a->id] < bbIdToDfsTimestamp_[b->id];
});
auto predBb = bb.preds.at(0);
predPc = predBb->end;
}
frameStateBuilder_.AdvenceToSuccessor(predPc, bb.end);
frameStateBuilder_.AdvenceToBasicBlock(bb.id);
ReverseEnumerateBlock(bb, [this, undefinedGate]
(uint8_t * pc, BytecodeInfo &bytecodeInfo) -> bool {
GateRef gate = Circuit::NullGate();
if (bytecodeInfo.IsMov()) {
// end def live range
if (bytecodeInfo.accOut) {
frameStateBuilder_.UpdateAccumulator(undefinedGate);
gate = frameStateBuilder_.ValuesAtAccumulator();
} else if (bytecodeInfo.vregOut.size() != 0) {
auto out = bytecodeInfo.vregOut[0];
gate = frameStateBuilder_.ValuesAt(out);
frameStateBuilder_.UpdateVirtualRegister(out, undefinedGate);
}
// start use live range
if (bytecodeInfo.accIn) {
frameStateBuilder_.UpdateAccumulator(gate);
} else if (bytecodeInfo.inputs.size() != 0) {
auto vreg = std::get<VirtualRegister>(bytecodeInfo.inputs.at(0)).GetId();
frameStateBuilder_.UpdateVirtualRegister(vreg, gate);
}
return true;
} else if (bytecodeInfo.IsGeneral() || bytecodeInfo.IsReturn() || bytecodeInfo.IsCondJump()) {
gate = byteCodeToJSGate_.at(pc);
}
// end def live range
if (bytecodeInfo.accOut) {
frameStateBuilder_.UpdateAccumulator(undefinedGate);
}
for (const auto &out: bytecodeInfo.vregOut) {
frameStateBuilder_.UpdateVirtualRegister(out, undefinedGate);
}
// start use live range
if (bytecodeInfo.accIn) {
auto id = bytecodeInfo.inputs.size();
GateRef def = gateAcc_.GetValueIn(gate, id);
frameStateBuilder_.UpdateAccumulator(def);
}
for (size_t i = 0; i < bytecodeInfo.inputs.size(); i++) {
auto in = bytecodeInfo.inputs[i];
if (std::holds_alternative<VirtualRegister>(in)) {
auto vreg = std::get<VirtualRegister>(in).GetId();
GateRef def = gateAcc_.GetValueIn(gate, i);
frameStateBuilder_.UpdateVirtualRegister(vreg, def);
}
}
// build guard
if (bytecodeInfo.deopt) {
GateRef glue = argAcc_.GetCommonArgGate(CommonArgIdx::GLUE);
frameStateBuilder_.BindGuard(gate, bytecodeInfo.pcOffset, glue);
}
return true;
});
// replace phi
if (bb.valueSelectorAccGate != Circuit::NullGate()) {
frameStateBuilder_.UpdateAccumulator(bb.valueSelectorAccGate);
auto reg = frameStateBuilder_.GetAccumulatorIndex();
FrameStateReplacePhi(bb.valueSelectorAccGate, reg);
}
for (auto &it : bb.vregToValSelectorGate) {
auto reg = it.first;
auto gate = it.second;
frameStateBuilder_.UpdateVirtualRegister(reg, gate);
FrameStateReplacePhi(gate, reg);
}
EnumerateBlock(bb, [this](uint8_t * pc, BytecodeInfo &bytecodeInfo) -> bool {
GateRef gate = Circuit::NullGate();
if (bytecodeInfo.IsMov()) {
if (bytecodeInfo.accIn) {
gate = frameStateBuilder_.ValuesAtAccumulator();
} else if (bytecodeInfo.inputs.size() != 0) {
auto index = std::get<VirtualRegister>(bytecodeInfo.inputs.at(0)).GetId();
gate = frameStateBuilder_.ValuesAt(index);
}
} else if (bytecodeInfo.IsGeneral()) {
gate = byteCodeToJSGate_.at(pc);
if (bytecodeInfo.deopt) {
GateRef glue = argAcc_.GetCommonArgGate(CommonArgIdx::GLUE);
frameStateBuilder_.BindGuard(gate, bytecodeInfo.pcOffset, glue, jsgateToBytecode_);
}
} else if (bytecodeInfo.IsSetConstant()) {
gate = byteCodeToJSGate_.at(pc);
}
if (bytecodeInfo.accOut) {
frameStateBuilder_.UpdateAccumulator(gate);
}
for (const auto &out: bytecodeInfo.vregOut) {
frameStateBuilder_.UpdateVirtualRegister(out, gate);
}
return true;
});
}
}

View File

@ -571,6 +571,23 @@ public:
}
}
template <class Callback>
void ReverseEnumerateBlock(BytecodeRegion &bb, const Callback &cb)
{
auto pc = bb.end;
while (true) {
auto bytecodeInfo = GetBytecodeInfo(pc);
bool ret = cb(pc, bytecodeInfo);
if (!ret) {
break;
}
pc = byteCodeCurPrePc_.at(pc);
if (pc <= bb.start || pc >= bb.end) {
break;
}
}
}
const std::map<const uint8_t *, int32_t> &GetPcToBCOffset() const
{
return pcToBCOffset_;
@ -583,7 +600,7 @@ private:
void ComputeDominatorTree();
void BuildImmediateDominator(const std::vector<size_t> &immDom);
void ComputeDomFrontiers(const std::vector<size_t> &immDom);
void RemoveDeadRegions();
void RemoveDeadRegions(const std::map<size_t, size_t> &bbIdToDfsTimestamp);
void InsertPhi();
void InsertExceptionPhi(std::map<uint16_t, std::set<size_t>> &defsitesInfo);
void UpdateCFG();
@ -606,6 +623,8 @@ private:
void NewPhi(BytecodeRegion &bb, uint16_t reg, bool acc, GateRef &currentPhi);
GateRef RenameVariable(const size_t bbId, const uint8_t *end, const uint16_t reg, const bool acc);
void BuildCircuit();
void BuildDfsList();
void FrameStateReplacePhi(GateRef phi, size_t reg);
void BuildFrameState();
GateRef GetExistingRestore(GateRef resumeGate, uint16_t tmpReg) const;
void SetExistingRestore(GateRef resumeGate, uint16_t tmpReg, GateRef restoreGate);
@ -641,7 +660,6 @@ private:
FrameStateBuilder frameStateBuilder_;
std::string methodName_;
std::vector<size_t> bbDfsList_;
std::map<size_t, size_t> bbIdToDfsTimestamp_; // (basicblock id, dfs order)
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H

View File

@ -375,29 +375,9 @@ GateRef CircuitBuilder::TaggedFalse()
GateRef CircuitBuilder::GetValueFromTaggedArray(GateRef array, GateRef index)
{
Label subentry(env_);
SubCfgEntry(&subentry);
Label exit(env_);
Label isUndefined(env_);
Label notUndefined(env_);
GateRef initVal = UndefineConstant();
DEFVAlUE(result, env_, VariableType::JS_ANY(), initVal);
Branch(TaggedIsUndefined(array), &isUndefined, &notUndefined);
Bind(&isUndefined);
{
Jump(&exit);
}
Bind(&notUndefined);
{
GateRef offset = PtrMul(ChangeInt32ToIntPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
result = Load(VariableType::JS_ANY(), array, dataOffset);
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
SubCfgExit();
return ret;
GateRef offset = PtrMul(ChangeInt32ToIntPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
return Load(VariableType::JS_ANY(), array, dataOffset);
}
void CircuitBuilder::SetValueToTaggedArray(VariableType valType, GateRef glue,

View File

@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/frame_states.h"
namespace panda::ecmascript::kungfu {
@ -24,7 +23,6 @@ FrameStateInfo *FrameStateInfo::Clone()
FrameStateBuilder::FrameStateBuilder(Circuit *circuit, const MethodLiteral *literal)
: literal_(literal), circuit_(circuit), gateAcc_(circuit)
{
currentInfo_ = new FrameStateInfo(literal_);
}
FrameStateBuilder::~FrameStateBuilder()
@ -37,62 +35,28 @@ FrameStateBuilder::~FrameStateBuilder()
currentInfo_ = nullptr;
}
void FrameStateBuilder::BuildArgsValues(ArgumentAccessor *argAcc)
void FrameStateBuilder::InitFrameValues()
{
auto callFieldNumVregs = literal_->GetNumVregsWithCallField();
auto values = currentInfo_->GetValues();
auto undefinedGate = circuit_->GetConstantGate(MachineType::I64,
JSTaggedValue::VALUE_UNDEFINED,
GateType::TaggedValue());
auto values = currentInfo_->GetValues();
for (size_t i = 0; i < callFieldNumVregs; i++) {
values->push_back(undefinedGate);
}
if (literal_->HaveFuncWithCallField()) {
auto gate = argAcc->GetCommonArgGate(CommonArgIdx::FUNC);
values->push_back(gate);
}
if (literal_->HaveNewTargetWithCallField()) {
auto gate = argAcc->GetCommonArgGate(CommonArgIdx::NEW_TARGET);
values->push_back(gate);
}
if (literal_->HaveThisWithCallField()) {
auto gate = argAcc->GetCommonArgGate(CommonArgIdx::THIS);
values->push_back(gate);
}
auto numArgs = literal_->GetNumArgsWithCallField();
auto numArgs = literal_->GetNumberVRegs();
for (size_t i = 0; i < numArgs; i++) {
auto gate = argAcc->ArgsAt(i + static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS));
values->push_back(gate);
values->push_back(undefinedGate);
}
// push acc
values->push_back(undefinedGate);
ASSERT(currentInfo_->GetNumberVRegs() == values->size());
}
GateRef FrameStateBuilder::FrameState(size_t pcOffset,
std::map<GateRef, std::pair<size_t, const uint8_t *>> &jsgateToBytecode)
GateRef FrameStateBuilder::FrameState(size_t pcOffset)
{
auto numVregs = currentInfo_->GetNumberVRegs();
size_t frameStateInputs = numVregs + 1; // +1: for pc
std::vector<GateRef> inList(frameStateInputs, Circuit::NullGate());
for (size_t i = 0; i < numVregs; i++) {
auto iter = jsgateToBytecode.find(ValuesAt(i));
if (iter != jsgateToBytecode.end()) {
auto pc = iter->second.second;
BytecodeInstruction inst(pc);
EcmaOpcode op = inst.GetOpcode();
// vreg needed remove from framstate if it comes from RESUMEGENERATOR, otherwisethe upperbound will not be
// found
if (op == EcmaOpcode::RESUMEGENERATOR) {
inList[i] = circuit_->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED,
GateType::TaggedValue());
} else {
inList[i] = ValuesAt(i);
}
} else {
inList[i] = ValuesAt(i);
}
inList[i] = ValuesAt(i);
}
auto pcGate = circuit_->GetConstantGate(MachineType::I64,
pcOffset,
@ -101,11 +65,10 @@ GateRef FrameStateBuilder::FrameState(size_t pcOffset,
return circuit_->NewGate(OpCode(OpCode::FRAME_STATE), frameStateInputs, inList, GateType::Empty());
}
void FrameStateBuilder::BindGuard(GateRef gate, size_t pcOffset, GateRef glue,
std::map<GateRef, std::pair<size_t, const uint8_t *>> &jsgateToBytecode)
void FrameStateBuilder::BindGuard(GateRef gate, size_t pcOffset, GateRef glue)
{
auto depend = gateAcc_.GetDep(gate);
GateRef frameState = FrameState(pcOffset, jsgateToBytecode);
GateRef frameState = FrameState(pcOffset);
auto trueGate = circuit_->GetConstantGate(MachineType::I1,
1, // 1: true
GateType::NJSValue());
@ -114,18 +77,19 @@ void FrameStateBuilder::BindGuard(GateRef gate, size_t pcOffset, GateRef glue,
gateAcc_.ReplaceDependIn(gate, guard);
}
void FrameStateBuilder::AdvenceToSuccessor(const uint8_t *predPc, const uint8_t *endPc)
void FrameStateBuilder::AdvenceToBasicBlock(size_t id)
{
size_t pcOffset = static_cast<size_t>(endPc - literal_->GetBytecodeArray());
if (predPc != nullptr) {
size_t predPcOffset = static_cast<size_t>(predPc - literal_->GetBytecodeArray());
auto predFrameInfo = stateInfos_[predPcOffset];
ASSERT(predFrameInfo != nullptr);
currentInfo_ = predFrameInfo;
currentInfo_ = CloneFrameState(pcOffset);
} else {
// for first block
stateInfos_[pcOffset] = currentInfo_;
if (currentInfo_ == nullptr) {
// for last block
currentInfo_ = new FrameStateInfo(literal_);
stateInfos_[id] = currentInfo_;
InitFrameValues();
return;
}
auto frameInfo = stateInfos_[id];
if (frameInfo == nullptr) {
frameInfo = CloneFrameState(currentInfo_, id);
}
currentInfo_ = frameInfo;
}
}

View File

@ -77,6 +77,10 @@ public:
SetValuesAt(index, gate);
}
FrameStateInfo *Clone();
size_t GetAccumulatorIndex() const
{
return accumulator_index_;
}
private:
size_t numVregs_ {0};
size_t accumulator_index_ {0};
@ -100,7 +104,6 @@ public:
return currentInfo_->ValuesAtAccumulator();
}
void BuildArgsValues(ArgumentAccessor *argAcc);
void UpdateAccumulator(GateRef gate)
{
currentInfo_->UpdateAccumulator(gate);
@ -109,19 +112,22 @@ public:
{
currentInfo_->UpdateVirtualRegister(index, gate);
}
void BindGuard(GateRef gate, size_t pcOffset, GateRef glue,
std::map<GateRef, std::pair<size_t, const uint8_t *>> &jsgateToBytecode);
void AdvenceToSuccessor(const uint8_t *predPc, const uint8_t *endPc);
private:
FrameStateInfo *CloneFrameState(size_t pcOffset)
void BindGuard(GateRef gate, size_t pcOffset, GateRef glue);
void AdvenceToBasicBlock(size_t id);
size_t GetAccumulatorIndex() const
{
ASSERT(stateInfos_[pcOffset] == nullptr);
auto info = currentInfo_->Clone();
stateInfos_[pcOffset] = info;
return currentInfo_->GetAccumulatorIndex();
}
private:
FrameStateInfo *CloneFrameState(FrameStateInfo *current, size_t id)
{
ASSERT(stateInfos_[id] == nullptr);
auto info = current->Clone();
stateInfos_[id] = info;
return info;
}
GateRef FrameState(size_t pcOffset, std::map<GateRef, std::pair<size_t, const uint8_t *>> &jsgateToBytecode);
GateRef FrameState(size_t pcOffset);
void InitFrameValues();
FrameStateInfo *currentInfo_{nullptr};
const MethodLiteral *literal_ {nullptr};

View File

@ -1269,17 +1269,17 @@ std::string Gate::GateTypeStr(GateType gateType) const
void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx) const
{
if (GetOpCode() != OpCode::NOP) {
std::string log("(id=" + std::to_string(id_) + ", op=" + GetOpCode().Str() + ", ");
log += ((bytecode.compare("") == 0) ? "" : "bytecode=") + bytecode;
log += ((bytecode.compare("") == 0) ? "" : ", ");
log += "MType=" + MachineTypeStr(GetMachineType()) + ", ";
std::string log("{\"id\":" + std::to_string(id_) + ", \"op\":\"" + GetOpCode().Str() + "\", ");
log += ((bytecode.compare("") == 0) ? "" : "\"bytecode\":\"") + bytecode;
log += ((bytecode.compare("") == 0) ? "" : "\", ");
log += "\"MType\":\"" + MachineTypeStr(GetMachineType()) + ", ";
std::stringstream buf;
buf << std::hex << bitfield_;
log += "bitfield=" + buf.str() + ", ";
log += "type=" + GateTypeStr(type_) + ", ";
log += "stamp=" + std::to_string(static_cast<uint32_t>(stamp_)) + ", ";
log += "mark=" + std::to_string(static_cast<uint32_t>(mark_)) + ", ";
log += "in=[";
log += "\",\"in\":[";
size_t idx = 0;
auto stateSize = GetStateCount();
@ -1293,7 +1293,7 @@ void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx)
PrintInGate(stateSize + dependSize + valueSize + rootSize, idx, stateSize + dependSize + valueSize,
inListPreview, highlightIdx, log, true);
log += "], out=[";
log += "], \"out\":[";
if (!IsFirstOutNull()) {
const Out *curOut = GetFirstOutConst();
@ -1302,12 +1302,12 @@ void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx)
while (!curOut->IsNextOutNull()) {
curOut = curOut->GetNextOutConst();
log += " " + std::to_string(curOut->GetGateConst()->GetId()) +
log += ", " + std::to_string(curOut->GetGateConst()->GetId()) +
(inListPreview ? std::string(":" + curOut->GetGateConst()->GetOpCode().Str())
: std::string(""));
}
}
log += "])";
log += "]},";
LOG_COMPILER(INFO) << std::dec << log;
}
}
@ -1315,15 +1315,15 @@ void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx)
void Gate::ShortPrint(std::string bytecode, bool inListPreview, size_t highlightIdx) const
{
if (GetOpCode() != OpCode::NOP) {
std::string log("(id=" + std::to_string(id_) + ", op=" + GetOpCode().Str() + ", ");
std::string log("(\"id\"=" + std::to_string(id_) + ", \"op\"=\"" + GetOpCode().Str() + "\", ");
log += ((bytecode.compare("") == 0) ? "" : "bytecode=") + bytecode;
log += ((bytecode.compare("") == 0) ? "" : ", ");
log += "MType=" + MachineTypeStr(GetMachineType()) + ", ";
log += "\"MType\"=\"" + MachineTypeStr(GetMachineType()) + ", ";
std::stringstream buf;
buf << std::hex << bitfield_;
log += "bitfield=" + buf.str() + ", ";
log += "type=" + GateTypeStr(type_) + ", ";
log += "in=[";
log += "\", in=[";
size_t idx = 0;
auto stateSize = GetStateCount();
@ -1346,7 +1346,7 @@ void Gate::ShortPrint(std::string bytecode, bool inListPreview, size_t highlight
while (!curOut->IsNextOutNull()) {
curOut = curOut->GetNextOutConst();
log += " " + std::to_string(curOut->GetGateConst()->GetId()) +
log += ", " + std::to_string(curOut->GetGateConst()->GetId()) +
(inListPreview ? std::string(":" + curOut->GetGateConst()->GetOpCode().Str())
: std::string(""));
}
@ -1361,7 +1361,7 @@ size_t Gate::PrintInGate(size_t numIns, size_t idx, size_t size, bool inListPrev
{
log += "[";
for (; idx < numIns; idx++) {
log += ((idx == size) ? "" : " ");
log += ((idx == size) ? "" : ", ");
log += ((idx == highlightIdx) ? "\033[4;31m" : "");
log += ((IsInGateNull(idx)
? "N"

View File

@ -457,4 +457,21 @@ void GateAccessor::DeleteGuardAndFrameState(GateRef gate)
DeleteGate(guard);
}
}
void GateAccessor::ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value)
{
auto uses = Uses(gate);
for (auto useIt = uses.begin(); useIt != uses.end();) {
if (IsStateIn(useIt)) {
useIt = ReplaceIn(useIt, state);
} else if (IsDependIn(useIt)) {
useIt = ReplaceIn(useIt, depend);
} else if (IsValueIn(useIt)) {
useIt = ReplaceIn(useIt, value);
} else {
UNREACHABLE();
}
}
DeleteGate(gate);
}
} // namespace panda::ecmascript::kungfu

View File

@ -364,6 +364,7 @@ public:
bool IsDependIn(GateRef gate, size_t index) const;
bool IsValueIn(GateRef gate, size_t index) const;
void DeleteGuardAndFrameState(GateRef gate);
void ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value);
private:
ConstUseIterator ConstUseBegin(GateRef gate) const

View File

@ -71,9 +71,6 @@ struct CodeInfo {
if (reqSecs_ == reinterpret_cast<uint8_t *>(-1)) {
reqSecs_ = nullptr;
}
// align machineCode for aarch64
reqSecs_ += MachineCode::DATA_OFFSET +
AlignUp(sizeof(Region), static_cast<size_t>(MemAlignment::MEM_ALIGN_REGION));
unreqSecs_ = static_cast<uint8_t *>(mmap(nullptr, UNREQUIRED_SECS_LIMIT, protRWX, flags, -1, 0));
if (unreqSecs_ == reinterpret_cast<uint8_t *>(-1)) {
unreqSecs_ = nullptr;
@ -84,8 +81,6 @@ struct CodeInfo {
{
Reset();
if (reqSecs_ != nullptr) {
reqSecs_ -= MachineCode::DATA_OFFSET +
AlignUp(sizeof(Region), static_cast<size_t>(MemAlignment::MEM_ALIGN_REGION));
munmap(reqSecs_, REQUIRED_SECS_LIMIT);
}
reqSecs_ = nullptr;

View File

@ -299,7 +299,7 @@ void SlowPathLowering::Lower(GateRef gate)
GateRef newTarget = argAcc_.GetCommonArgGate(CommonArgIdx::NEW_TARGET);
GateRef jsFunc = argAcc_.GetCommonArgGate(CommonArgIdx::FUNC);
GateRef actualArgc = argAcc_.GetCommonArgGate(CommonArgIdx::ACTUAL_ARGC);
GateRef thisObj = argAcc_.GetCommonArgGate(CommonArgIdx::THIS);
GateRef thisObj = argAcc_.GetCommonArgGate(CommonArgIdx::THIS_OBJECT);
auto pc = bcBuilder_->GetJSBytecode(gate);
EcmaOpcode op = bcBuilder_->PcToOpcode(pc);
@ -869,7 +869,7 @@ void SlowPathLowering::SaveFrameToContext(GateRef gate, GateRef glue, GateRef js
// set this
GateRef thisOffset = builder_.IntPtr(GeneratorContext::GENERATOR_THIS_OFFSET);
GateRef thisObj = argAcc_.GetCommonArgGate(CommonArgIdx::THIS);
GateRef thisObj = argAcc_.GetCommonArgGate(CommonArgIdx::THIS_OBJECT);
builder_.Store(VariableType::JS_ANY(), glue, context, thisOffset, thisObj);
// set method
@ -2851,7 +2851,7 @@ void SlowPathLowering::LowerStObjByValue(GateRef gate, GateRef glue, GateRef thi
{
GateRef undefined = builder_.UndefineConstant();
result = LowerCallRuntime(glue, RTSTUB_ID(StoreICByValue), {undefined, receiver, propKey, accValue,
builder_.ToTaggedInt(undefined)});
builder_.ToTaggedInt(builder_.Int64(0))});
builder_.Branch(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION),
&exceptionExit, &successExit);
}

View File

@ -1023,17 +1023,16 @@ void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler)
__ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
__ Add(sp, sp, Immediate(DOUBLE_SLOT_SIZE)); // 2: skip runtimeId argc
__ CalleeRestore();
Register context(X2);
__ Mov(context, Register(X0));
__ Ldr(glueReg, MemoryOperand(sp, 0));
Register ret(X0);
Label stackOverflow;
__ Cmp(ret, Immediate(JSTaggedValue::VALUE_EXCEPTION));
__ B(Condition::EQ, &stackOverflow);
__ CalleeRestore();
Register context(X2);
__ Mov(context, Register(X0));
__ Ldr(glueReg, MemoryOperand(sp, 0));
Label target;
Register temp(X1);
__ Ldr(fp, MemoryOperand(context, AsmStackContext::GetCallerFpOffset(false)));
@ -1054,9 +1053,7 @@ void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler)
// 2 : 2 means pair
__ Stp(runtimeId, Register(Zero), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
__ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
__ Add(sp, sp, Immediate(DOUBLE_SLOT_SIZE)); // 2: skip runtimeId argc
__ CalleeRestore();
__ Add(sp, sp, Immediate(2 * DOUBLE_SLOT_SIZE)); // 2: skip runtimeId&argc glue&type
__ RestoreFpAndLr();
__ Ret();
}

View File

@ -1272,29 +1272,31 @@ void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(DeoptHandlerAsm));
Register glueReg = rdi;
__ Pushq(rbp);
__ Movq(rsp, rbp);
__ Pushq(static_cast<int32_t>(FrameType::OPTIMIZED_FRAME));
__ Push(glueReg);
__ PushCppCalleeSaveRegisters();
Register glueReg = rdi;
__ Push(glueReg);
__ Movq(rdi, rax); // glue
__ PushAlignBytes();
__ Pushq(0); // argc
__ Pushq(kungfu::RuntimeStubCSigns::ID_DeoptHandler);
__ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
__ Addq(3 * FRAME_SLOT_SIZE, rsp); // 3: skip runtimeId argc argv[0] argv[1]
__ Pop(glueReg);
__ Addq(3 * FRAME_SLOT_SIZE, rsp); // 3: skip runtimeId argc & align
Register context = rsi;
__ Movq(rax, context);
Label target;
__ PopCppCalleeSaveRegisters();
__ Pop(glueReg);
Label stackOverflow;
__ Cmpq(JSTaggedValue::VALUE_EXCEPTION, rax);
__ Je(&stackOverflow);
Label target;
__ PopCppCalleeSaveRegisters();
__ Movq(Operand(context, AsmStackContext::GetCallerFpOffset(false)), rbp);
__ Movq(Operand(context, AsmStackContext::GetCallFrameTopOffset(false)), rsp);
__ Subq(FRAME_SLOT_SIZE, rsp); // skip lr
@ -1313,10 +1315,7 @@ void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler)
__ Pushq(0); // argc
__ Pushq(kungfu::RuntimeStubCSigns::ID_ThrowStackOverflowException);
__ CallAssemblerStub(RTSTUB_ID(CallRuntime), false);
__ Addq(16, rsp); // 16: skip runtimeId argc
__ PopCppCalleeSaveRegisters();
__ Addq(FRAME_SLOT_SIZE, rsp);
__ Addq(FRAME_SLOT_SIZE * 3, rsp); // skip runtimeId argc & type
__ Popq(rbp);
__ Ret();
}

View File

@ -432,9 +432,10 @@ void TSTypeLowering::SpeculateNumbers(GateRef gate)
// guard maybe not a GUARD
GateRef guard = acc_.GetDep(gate);
if (check != Circuit::NullGate()) {
ASSERT(acc_.GetOpCode(guard) == OpCode::GUARD);
acc_.ReplaceIn(guard, 1, check);
}
// Replace the old NumberBinaryOp<Op> with TypedBinaryOp<Op>
GateRef result = builder_.TypedBinaryOp<Op>(left, right, leftType, rightType, gateType);
@ -460,6 +461,7 @@ void TSTypeLowering::SpeculateNumber(GateRef gate)
// guard maybe not a GUARD
GateRef guard = acc_.GetDep(gate);
if (check != Circuit::NullGate()) {
ASSERT(acc_.GetOpCode(guard) == OpCode::GUARD);
acc_.ReplaceIn(guard, 1, check);
}
@ -496,6 +498,7 @@ void TSTypeLowering::LowerPrimitiveTypeToNumber(GateRef gate)
// guard maybe not a GUARD
GateRef guard = acc_.GetDep(gate);
if (check != Circuit::NullGate()) {
ASSERT(acc_.GetOpCode(guard) == OpCode::GUARD);
acc_.ReplaceIn(guard, 1, check);
}
@ -520,23 +523,6 @@ void TSTypeLowering::SpeculateConditionJump(GateRef gate)
GateRef value = acc_.GetValueIn(gate, 0);
GateRef condition = builder_.IsSpecial(value, JSTaggedValue::VALUE_FALSE);
GateRef ifBranch = builder_.Branch(acc_.GetState(gate), condition);
ReplaceGate(gate, ifBranch, builder_.GetDepend(), Circuit::NullGate());
}
void TSTypeLowering::ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value)
{
auto uses = acc_.Uses(gate);
for (auto useIt = uses.begin(); useIt != uses.end();) {
if (acc_.IsStateIn(useIt)) {
useIt = acc_.ReplaceIn(useIt, state);
} else if (acc_.IsDependIn(useIt)) {
useIt = acc_.ReplaceIn(useIt, depend);
} else if (acc_.IsValueIn(useIt)) {
useIt = acc_.ReplaceIn(useIt, value);
} else {
UNREACHABLE();
}
}
acc_.DeleteGate(gate);
acc_.ReplaceGate(gate, ifBranch, builder_.GetDepend(), Circuit::NullGate());
}
} // namespace panda::ecmascript

View File

@ -48,7 +48,6 @@ private:
void DeleteGates(GateRef hir, std::vector<GateRef> &unusedGate);
void ReplaceHIRGate(GateRef hir, GateRef outir, GateRef state, GateRef depend,
std::vector<GateRef> &unuseGate);
void ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value);
void LowerTypedAdd(GateRef gate);
void LowerTypedSub(GateRef gate);
void LowerTypedMul(GateRef gate);

View File

@ -98,7 +98,7 @@ void TypeLowering::LowerPrimitiveToNumber(GateRef dst, GateRef src, GateType src
UNREACHABLE();
}
builder_.Bind(&exit);
ReplaceGate(dst, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(dst, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerTypeCheck(GateRef gate)
@ -388,7 +388,7 @@ void TypeLowering::LowerNumberAdd(GateRef gate)
GateType rightType = GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = CalculateNumbers<OpCode::ADD>(left, right, leftType, rightType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberSub(GateRef gate)
@ -399,7 +399,7 @@ void TypeLowering::LowerNumberSub(GateRef gate)
GateType rightType = GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = CalculateNumbers<OpCode::SUB>(left, right, leftType, rightType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberMul(GateRef gate)
@ -410,7 +410,7 @@ void TypeLowering::LowerNumberMul(GateRef gate)
GateType rightType = GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = CalculateNumbers<OpCode::MUL>(left, right, leftType, rightType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberLess(GateRef gate)
@ -421,7 +421,7 @@ void TypeLowering::LowerNumberLess(GateRef gate)
GateType rightType = GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = CompareNumbers<TypedBinOp::TYPED_LESS>(left, right, leftType, rightType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberLessEq(GateRef gate)
@ -432,7 +432,7 @@ void TypeLowering::LowerNumberLessEq(GateRef gate)
GateType rightType = GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = CompareNumbers<TypedBinOp::TYPED_LESSEQ>(left, right, leftType, rightType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberGreater(GateRef gate)
@ -443,7 +443,7 @@ void TypeLowering::LowerNumberGreater(GateRef gate)
GateType rightType = GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = CompareNumbers<TypedBinOp::TYPED_LESS>(right, left, rightType, leftType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberGreaterEq(GateRef gate)
@ -454,7 +454,7 @@ void TypeLowering::LowerNumberGreaterEq(GateRef gate)
GateType rightType = GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = CompareNumbers<TypedBinOp::TYPED_LESSEQ>(right, left, rightType, leftType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberDiv(GateRef gate)
@ -465,7 +465,7 @@ void TypeLowering::LowerNumberDiv(GateRef gate)
GateType rightType = GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = DivNumbers(left, right, leftType, rightType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberEq(GateRef gate)
@ -476,7 +476,7 @@ void TypeLowering::LowerNumberEq(GateRef gate)
GateType rightType = GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = CompareNumbers<TypedBinOp::TYPED_EQ>(left, right, leftType, rightType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberNotEq(GateRef gate)
@ -487,7 +487,7 @@ void TypeLowering::LowerNumberNotEq(GateRef gate)
GateType rightType = GetRightType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = CompareNumbers<TypedBinOp::TYPED_NOTEQ>(left, right, leftType, rightType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberInc(GateRef gate)
@ -496,7 +496,7 @@ void TypeLowering::LowerNumberInc(GateRef gate)
GateType valueType = GetLeftType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = MonocularNumber<TypedUnOp::TYPED_INC>(value, valueType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::LowerNumberDec(GateRef gate)
@ -505,24 +505,7 @@ void TypeLowering::LowerNumberDec(GateRef gate)
GateType valueType = GetLeftType(gate);
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
result = MonocularNumber<TypedUnOp::TYPED_DEC>(value, valueType);
ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypeLowering::ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value)
{
auto uses = acc_.Uses(gate);
for (auto useIt = uses.begin(); useIt != uses.end();) {
if (acc_.IsStateIn(useIt)) {
useIt = acc_.ReplaceIn(useIt, state);
} else if (acc_.IsDependIn(useIt)) {
useIt = acc_.ReplaceIn(useIt, depend);
} else if (acc_.IsValueIn(useIt)) {
useIt = acc_.ReplaceIn(useIt, value);
} else {
UNREACHABLE();
}
}
acc_.DeleteGate(gate);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
template<OpCode::Op Op>

View File

@ -154,7 +154,6 @@ private:
void LowerNumberNotEq(GateRef gate);
void LowerNumberInc(GateRef gate);
void LowerNumberDec(GateRef gate);
void ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value);
template<OpCode::Op Op>
GateRef FastAddOrSubOrMul(GateRef left, GateRef right);

View File

@ -20,11 +20,6 @@
#include "ecmascript/stubs/runtime_stubs-inl.h"
namespace panda::ecmascript {
using DeoptFromAOTType = JSTaggedType (*)(uintptr_t glue, JSTaggedType* sp,
uintptr_t vregsSp, uintptr_t stateSp, JSTaggedType callTarget);
static constexpr size_t LEXENV_INDEX = 1;
static constexpr size_t THIS_VALUE_INDEX = 5;
class FrameWriter {
public:
explicit FrameWriter(Deoptimizier *deoptimizier) : thread_(deoptimizier->GetThread())
@ -73,7 +68,7 @@ private:
void Deoptimizier::CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle)
{
vregs_.clear();
deoptVregs_.clear();
for (size_t i = 0; i < deoptBundle.size(); i++) {
kungfu::ARKDeopt deopt = deoptBundle.at(i);
JSTaggedType v;
@ -100,7 +95,7 @@ void Deoptimizier::CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle
v = JSTaggedType(static_cast<int64_t>(std::get<kungfu::OffsetType>(deopt.value)));
}
if (id != static_cast<kungfu::OffsetType>(SpecVregIndex::PC_INDEX)) {
vregs_[id] = JSTaggedValue(v);
deoptVregs_[id] = JSTaggedValue(v);
} else {
pc_ = static_cast<uint32_t>(v);
}
@ -122,23 +117,18 @@ void Deoptimizier::CollectDeoptBundleVec(std::vector<kungfu::ARKDeopt>& deoptBun
context_.calleeRegAndOffset = calleeRegInfo;
context_.callsiteSp = it.GetCallSiteSp();
context_.callsiteFp = reinterpret_cast<uintptr_t>(it.GetSp());
context_.preFrameSp = frame->ComputePrevFrameSp(it);
context_.returnAddr = frame->GetReturnAddr();
uint64_t argc = frame->GetArgc(context_.preFrameSp);
auto argv = frame->GetArgv(reinterpret_cast<uintptr_t *>(context_.preFrameSp));
if (argc > 0) {
ASSERT(argc >= FIXED_NUM_ARGS);
callTarget_ = JSTaggedValue(argv[0]);
}
AotArgvs_ = argv;
auto preFrameSp = frame->ComputePrevFrameSp(it);
frameArgc_ = frame->GetArgc(preFrameSp);
frameArgvs_ = frame->GetArgv(preFrameSp);
env_ = frame->GetEnv();
stackContext_.callFrameTop_ = it.GetPrevFrameCallSiteSp();
stackContext_.returnAddr_ = context_.returnAddr;
stackContext_.returnAddr_ = frame->GetReturnAddr();
stackContext_.callerFp_ = reinterpret_cast<uintptr_t>(frame->GetPrevFrameFp());
break;
}
case FrameType::OPTIMIZED_FRAME: {
auto sp = reinterpret_cast<uintptr_t*>(it.GetSp());
sp--; // skip type
sp -= 2; // 2: skip type & glue
calleeRegAddr_ = sp - numCalleeRegs_;
break;
}
@ -173,33 +163,90 @@ void Deoptimizier::RelocateCalleeSave()
}
}
bool Deoptimizier::CollectVirtualRegisters(Method* method, FrameWriter *frameWriter)
{
int32_t actualNumArgs = static_cast<int32_t>(frameArgc_) - NUM_MANDATORY_JSFUNC_ARGS;
bool haveExtra = method->HaveExtraWithCallField();
int32_t declaredNumArgs = static_cast<int32_t>(method->GetNumArgsWithCallField());
int32_t callFieldNumVregs = static_cast<int32_t>(method->GetNumVregsWithCallField());
// layout of frame:
// [maybe argc] [actual args] [reserved args] [call field virtual regs]
// [maybe argc]
if (declaredNumArgs != actualNumArgs && haveExtra) {
auto value = JSTaggedValue(actualNumArgs);
frameWriter->PushValue(value.GetRawData());
}
int32_t reservedCount = std::max(actualNumArgs, declaredNumArgs);
int32_t virtualIndex = reservedCount + callFieldNumVregs +
static_cast<int32_t>(method->GetNumRevervedArgs()) - 1;
if (!frameWriter->Reserve(static_cast<size_t>(virtualIndex))) {
return false;
}
// [actual args]
if (declaredNumArgs > actualNumArgs) {
frameWriter->PushValue(JSTaggedValue::Undefined().GetRawData());
virtualIndex--;
}
for (int32_t i = actualNumArgs - 1; i >= 0; i--) {
JSTaggedValue value = JSTaggedValue::Undefined();
// deopt value
if (hasDeoptValue(virtualIndex)) {
value = deoptVregs_.at(static_cast<kungfu::OffsetType>(virtualIndex));
} else {
value = GetActualFrameArgs(i);
}
frameWriter->PushValue(value.GetRawData());
virtualIndex--;
}
// [reserved args]
if (method->HaveThisWithCallField()) {
JSTaggedValue value = GetFrameArgv(kungfu::CommonArgIdx::THIS_OBJECT);
frameWriter->PushValue(value.GetRawData());
virtualIndex--;
}
if (method->HaveNewTargetWithCallField()) {
JSTaggedValue value = GetFrameArgv(kungfu::CommonArgIdx::NEW_TARGET);
frameWriter->PushValue(value.GetRawData());
virtualIndex--;
}
if (method->HaveFuncWithCallField()) {
JSTaggedValue value = GetFrameArgv(kungfu::CommonArgIdx::FUNC);
frameWriter->PushValue(value.GetRawData());
virtualIndex--;
}
// [call field virtual regs]
for (int32_t i = virtualIndex; i >= 0; i--) {
JSTaggedValue value = JSTaggedValue::Undefined();
if (hasDeoptValue(virtualIndex)) {
value = deoptVregs_.at(static_cast<kungfu::OffsetType>(virtualIndex));
}
frameWriter->PushValue(value.GetRawData());
virtualIndex--;
}
return true;
}
JSTaggedType Deoptimizier::ConstructAsmInterpretFrame()
{
ASSERT(thread_ != nullptr);
auto fun = callTarget_;
JSTaggedValue callTarget = GetFrameArgv(kungfu::CommonArgIdx::FUNC);
FrameWriter frameWriter(this);
// Push asm interpreter frame
auto method = GetMethod(callTarget_);
auto numVRegs = method->GetNumberVRegs();
if (!frameWriter.Reserve(numVRegs)) {
auto method = GetMethod(callTarget);
if (!CollectVirtualRegisters(method, &frameWriter)) {
return JSTaggedValue::Exception().GetRawData();
}
for (int32_t i = numVRegs - 1; i >= 0; i--) {
JSTaggedValue value = JSTaggedValue::Undefined();
if (vregs_.find(static_cast<kungfu::OffsetType>(i)) != vregs_.end()) {
value = vregs_.at(static_cast<kungfu::OffsetType>(i));
}
frameWriter.PushValue(value.GetRawData());
}
const uint8_t *resumePc = method->GetBytecodeArray() + pc_;
AsmInterpretedFrame *statePtr = frameWriter.ReserveAsmInterpretedFrame();
JSTaggedValue env = JSTaggedValue(GetArgv(LEXENV_INDEX));
JSTaggedValue thisObj = JSTaggedValue(GetArgv(THIS_VALUE_INDEX));
auto acc = vregs_.at(static_cast<kungfu::OffsetType>(SpecVregIndex::ACC_INDEX));
statePtr->function = fun;
JSTaggedValue thisObj = GetFrameArgv(kungfu::CommonArgIdx::THIS_OBJECT);;
auto acc = deoptVregs_.at(static_cast<kungfu::OffsetType>(SpecVregIndex::ACC_INDEX));
statePtr->function = callTarget;
statePtr->acc = acc;
statePtr->env = env;
statePtr->env = env_;
statePtr->callSize = 0;
statePtr->fp = 0; // need update
statePtr->thisObj = thisObj;

View File

@ -17,6 +17,7 @@
#define ECMASCRIPT_DEOPTIMIZER_H
#include "ecmascript/base/aligned_struct.h"
#include "ecmascript/calleeReg.h"
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/js_handle.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/llvm_stackmap_type.h"
@ -34,8 +35,6 @@ enum class SpecVregIndex: int {
struct Context {
uintptr_t callsiteSp;
uintptr_t callsiteFp;
uintptr_t* preFrameSp;
uintptr_t returnAddr;
kungfu::CalleeRegAndOffsetVec calleeRegAndOffset;
};
@ -86,22 +85,18 @@ struct AsmStackContext : public base::AlignedStruct<base::AlignedPointer::Size()
// out put data
};
class Deoptimizier {
class FrameWriter;
class Deoptimizier
{
public:
static constexpr uint64_t LLVM_DEOPT_RELOCATE_ADDR = 0xabcdef0f;
explicit Deoptimizier(JSThread * thread) : thread_(thread)
{
Deoptimizier(JSThread * thread) : thread_(thread) {
kungfu::CalleeReg callreg;
numCalleeRegs_ = callreg.GetCallRegNum();
}
void CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle);
void CollectDeoptBundleVec(std::vector<kungfu::ARKDeopt>& deoptBundle);
JSTaggedType ConstructAsmInterpretFrame();
JSTaggedType GetArgv(int idx)
{
ASSERT(AotArgvs_ != nullptr);
return AotArgvs_[static_cast<int>(idx)];
}
JSThread *GetThread() const
{
@ -109,6 +104,30 @@ public:
}
private:
size_t GetFrameIndex(kungfu::CommonArgIdx index)
{
return static_cast<size_t>(index) - static_cast<size_t>(kungfu::CommonArgIdx::FUNC);
}
JSTaggedValue GetFrameArgv(size_t idx)
{
ASSERT(frameArgvs_ != nullptr);
ASSERT(idx < frameArgc_);
return JSTaggedValue(frameArgvs_[idx]);
}
JSTaggedValue GetFrameArgv(kungfu::CommonArgIdx index)
{
return GetFrameArgv(GetFrameIndex(index));
}
JSTaggedValue GetActualFrameArgs(int32_t index)
{
index += NUM_MANDATORY_JSFUNC_ARGS;
return GetFrameArgv(static_cast<size_t>(index));
}
bool CollectVirtualRegisters(Method* method, FrameWriter *frameWriter);
bool hasDeoptValue(int32_t index)
{
return deoptVregs_.find(static_cast<kungfu::OffsetType>(index)) != deoptVregs_.end();
}
Method* GetMethod(JSTaggedValue &target);
void RelocateCalleeSave();
JSThread *thread_ {nullptr};
@ -116,11 +135,12 @@ private:
size_t numCalleeRegs_ {0};
AsmStackContext stackContext_;
std::unordered_map<kungfu::OffsetType, JSTaggedValue> vregs_;
struct Context context_ {0, 0, nullptr, 0, {}};
std::unordered_map<kungfu::OffsetType, JSTaggedValue> deoptVregs_;
struct Context context_ {0, 0, {}};
uint32_t pc_;
JSTaggedValue callTarget_ {JSTaggedValue::Undefined()};
JSTaggedType *AotArgvs_ {nullptr};
JSTaggedValue env_ {JSTaggedValue::Undefined()};
size_t frameArgc_ {0};
JSTaggedType *frameArgvs_ {nullptr};
};
} // namespace panda::ecmascript

View File

@ -122,7 +122,12 @@ public:
uint32_t GetNumArgs() const
{
return GetNumArgsWithCallField() + HaveFuncWithCallField() +
return GetNumArgsWithCallField() + GetNumRevervedArgs();
}
uint32_t GetNumRevervedArgs() const
{
return HaveFuncWithCallField() +
HaveNewTargetWithCallField() + HaveThisWithCallField();
}

View File

@ -61,6 +61,7 @@ group("ark_typeinfer_test") {
"trystglobalbyname:trystglobalbynameAotTypeInferAction",
"tsarraytobuiltin:tsarraytobuiltinAotTypeInferAction",
"typeof:typeofAotTypeInferAction",
"variable_after_loops:variable_after_loopsAotTypeInferAction",
#"variable_after_loops:variable_after_loopsAotTypeInferAction",
]
}