Skip to content

Commit

Permalink
Remove AllocObjectLiteral
Browse files Browse the repository at this point in the history
Summary: `AllocObjectLiteral` is now unused.

Reviewed By: tmikov

Differential Revision: D30626994

fbshipit-source-id: 59e4c1c2acedff6c45b0ff0197139ec632cd6e48
  • Loading branch information
neildhar authored and facebook-github-bot committed Sep 9, 2023
1 parent 83e7989 commit 4203296
Show file tree
Hide file tree
Showing 13 changed files with 12 additions and 278 deletions.
10 changes: 0 additions & 10 deletions doc/IR.md
Original file line number Diff line number Diff line change
Expand Up @@ -496,16 +496,6 @@ Arguments | *%sizeHint% indicates that the object will need at least that many p
Semantics | The instruction creates a new JavaScript object on the heap. If the parent is invalid (not EmptySenyinel, null or object), it is silently ignored.
Effects | Does not read or write to memory.

### AllocObjectLiteralInst

AllocObjectLiteralInst | _
--- | --- |
Description | Allocates a new JavaScript object on the heap. During lowering pass it will be lowered to either an AllocObjectInst or a HBCAllocObjectFromBufferInst.
Example | %0 = AllocObjectLiteralInst "prop1" : string, 10 : number
Arguments | %prop_map is a vector of (Literal*, value*) pairs which represents the properties and their keys in the object literal.
Semantics | The instruction creates a new JavaScript object on the heap with an initial list of properties.
Effects | Does not read or write to memory.

### AllocArrayInst

AllocArrayInst | _
Expand Down
16 changes: 0 additions & 16 deletions include/hermes/BCGen/Lowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,22 +74,6 @@ class LowerAllocObject : public FunctionPass {
bool hasParent);
};

/// Lowers AllocObjectLiterals which target object literals with
/// constant properties.
class LowerAllocObjectLiteral : public FunctionPass {
public:
explicit LowerAllocObjectLiteral()
: FunctionPass("LowerAllocObjectLiteral") {}
~LowerAllocObjectLiteral() override = default;

bool runOnFunction(Function *F) override;

private:
uint32_t estimateBestNumElemsToSerialize(AllocObjectLiteralInst *allocInst);
bool lowerAlloc(AllocObjectLiteralInst *allocInst);
bool lowerAllocObjectBuffer(AllocObjectLiteralInst *allocInst);
};

/// Lowers Store instructions down to MOVs after register allocation.
class LowerStoreInstrs : public FunctionPass {
public:
Expand Down
3 changes: 0 additions & 3 deletions include/hermes/IR/IRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,9 +420,6 @@ class IRBuilder {
uint32_t size,
Value *parent = nullptr);

AllocObjectLiteralInst *createAllocObjectLiteralInst(
const AllocObjectLiteralInst::ObjectPropertyMap &propMap);

AllocArrayInst *createAllocArrayInst(
LiteralNumber *sizeHint,
AllocArrayInst::ArrayValueList val_list);
Expand Down
1 change: 0 additions & 1 deletion include/hermes/IR/Instrs.def
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ DEF_VALUE(StoreFrameInst, Instruction)
DEF_VALUE(AllocStackInst, Instruction)
DEF_VALUE(AllocObjectInst, Instruction)
DEF_VALUE(AllocArrayInst, Instruction)
DEF_VALUE(AllocObjectLiteralInst, Instruction)
DEF_VALUE(CreateArgumentsInst, Instruction)
DEF_VALUE(CatchInst, Instruction)
DEF_VALUE(DebuggerInst, Instruction)
Expand Down
47 changes: 0 additions & 47 deletions include/hermes/IR/Instrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1625,53 +1625,6 @@ class HBCAllocObjectFromBufferInst : public Instruction {
}
};

class AllocObjectLiteralInst : public Instruction {
AllocObjectLiteralInst(const AllocObjectLiteralInst &) = delete;
void operator=(const AllocObjectLiteralInst &) = delete;

public:
using ObjectPropertyMap =
llvh::SmallVector<std::pair<LiteralString *, Value *>, 4>;

explicit AllocObjectLiteralInst(const ObjectPropertyMap &propMap)
: Instruction(ValueKind::AllocObjectLiteralInstKind) {
setType(Type::createObject());
for (size_t i = 0; i < propMap.size(); i++) {
pushOperand(propMap[i].first);
pushOperand(propMap[i].second);
}
}

explicit AllocObjectLiteralInst(
const AllocObjectLiteralInst *src,
llvh::ArrayRef<Value *> operands)
: Instruction(src, operands) {}

SideEffectKind getSideEffect() {
return SideEffectKind::None;
}

WordBitSet<> getChangedOperandsImpl() {
return {};
}

unsigned getKeyValuePairCount() const {
return getNumOperands() / 2;
}

static bool classof(const Value *V) {
return kindIsA(V->getKind(), ValueKind::AllocObjectLiteralInstKind);
}

Literal *getKey(unsigned index) const {
return cast<Literal>(getOperand(2 * index));
}

Value *getValue(unsigned index) const {
return getOperand(2 * index + 1);
}
};

class AllocArrayInst : public Instruction {
AllocArrayInst(const AllocArrayInst &) = delete;
void operator=(const AllocArrayInst &) = delete;
Expand Down
3 changes: 0 additions & 3 deletions lib/BCGen/HBC/HBC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ void lowerIR(Module *M, const BytecodeGenerationOptions &options) {
// It is important to run LowerNumericProperties before LoadConstants
// as LowerNumericProperties could generate new constants.
PM.addPass<LowerNumericProperties>();
// Lower AllocObjectLiteral into a mixture of HBCAllocObjectFromBufferInst,
// AllocObjectInst, StoreNewOwnPropertyInst and StorePropertyInst.
PM.addPass<LowerAllocObjectLiteral>();
PM.addPass<LowerConstruction>();
PM.addPass<LowerArgumentsArray>();
PM.addPass<LimitAllocArray>(UINT16_MAX);
Expand Down
6 changes: 0 additions & 6 deletions lib/BCGen/HBC/ISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -808,12 +808,6 @@ void HBCISel::generateAllocObjectInst(AllocObjectInst *Inst, BasicBlock *next) {
BCFGen_->emitNewObjectWithParent(result, parentReg);
}
}
void HBCISel::generateAllocObjectLiteralInst(
AllocObjectLiteralInst *,
BasicBlock *) {
// This instruction should not have reached this far.
llvm_unreachable("AllocObjectLiteralInst should have been lowered.");
}
void HBCISel::generateAllocArrayInst(AllocArrayInst *Inst, BasicBlock *next) {
auto dstReg = encodeValue(Inst);
auto elementCount = Inst->getElementCount();
Expand Down
167 changes: 5 additions & 162 deletions lib/BCGen/Lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,15 +301,12 @@ static constexpr uint32_t kNonLiteralPlaceholderLimit = 3;

/// Whether the given value \v V can be serialized into the object literal
/// buffer.
static bool isSerializableLiteral(Value *V) {
return V &&
(llvh::isa<LiteralNull>(V) || llvh::isa<LiteralBool>(V) ||
llvh::isa<LiteralNumber>(V) || llvh::isa<LiteralString>(V));
}

static bool canSerialize(Value *V) {
if (auto *LCI = llvh::dyn_cast_or_null<HBCLoadConstInst>(V))
return isSerializableLiteral(LCI->getConst());
if (auto *LCI = llvh::dyn_cast_or_null<HBCLoadConstInst>(V)) {
Literal *L = LCI->getConst();
return llvh::isa<LiteralNull>(L) || llvh::isa<LiteralBool>(L) ||
llvh::isa<LiteralNumber>(L) || llvh::isa<LiteralString>(L);
}
return false;
}

Expand Down Expand Up @@ -444,155 +441,6 @@ bool LowerAllocObject::lowerAllocObjectBuffer(
return true;
}

bool LowerAllocObjectLiteral::runOnFunction(Function *F) {
bool changed = false;
llvh::SmallVector<AllocObjectLiteralInst *, 4> allocs;
for (BasicBlock &BB : *F) {
// We need to increase the iterator before calling lowerAllocObjectBuffer.
// Otherwise deleting the instruction will invalidate the iterator.
for (auto it = BB.begin(), e = BB.end(); it != e;) {
if (auto *A = llvh::dyn_cast<AllocObjectLiteralInst>(&*it++)) {
changed |= lowerAllocObjectBuffer(A);
}
}
}

return changed;
}

bool LowerAllocObjectLiteral::lowerAlloc(AllocObjectLiteralInst *allocInst) {
Function *F = allocInst->getParent()->getParent();
IRBuilder builder(F);

auto size = allocInst->getKeyValuePairCount();

// Replace AllocObjectLiteral with a regular AllocObject
builder.setLocation(allocInst->getLocation());
builder.setCurrentSourceLevelScope(allocInst->getSourceLevelScope());
builder.setInsertionPoint(allocInst);
auto *Obj = builder.createAllocObjectInst(size, nullptr);

for (unsigned i = 0; i < allocInst->getKeyValuePairCount(); i++) {
Literal *key = allocInst->getKey(i);
Value *value = allocInst->getValue(i);
builder.createStoreNewOwnPropertyInst(
value, allocInst, key, IRBuilder::PropEnumerable::Yes);
}
allocInst->replaceAllUsesWith(Obj);
allocInst->eraseFromParent();

return true;
}

uint32_t LowerAllocObjectLiteral::estimateBestNumElemsToSerialize(
AllocObjectLiteralInst *allocInst) {
// Reuse calc logic from LowerAllocObject.
int32_t curSaving = static_cast<int32_t>(sizeof(inst::NewObjectInst)) -
static_cast<int32_t>(sizeof(inst::NewObjectWithBufferInst));
int32_t maxSaving = 0;
uint32_t optimumStopIndex = 0;
uint32_t nonLiteralPlaceholderCount = 0;

uint32_t curSize = 0;
for (unsigned i = 0; i < allocInst->getKeyValuePairCount(); i++) {
++curSize;
Literal *key = allocInst->getKey(i);
Value *value = allocInst->getValue(i);
if (isSerializableLiteral(value)) {
curSaving += kLiteralSavedBytes;
if (curSaving > maxSaving) {
maxSaving = curSaving;
optimumStopIndex = curSize;
}
} else {
if (llvh::isa<LiteralNumber>(key)) {
continue;
}
if (nonLiteralPlaceholderCount == kNonLiteralPlaceholderLimit) {
// We have reached the maximum number of place holders we can put.
break;
}
nonLiteralPlaceholderCount++;
curSaving -= kNonLiteralCostBytes;
}
}
return optimumStopIndex;
}

bool LowerAllocObjectLiteral::lowerAllocObjectBuffer(
AllocObjectLiteralInst *allocInst) {
Function *F = allocInst->getParent()->getParent();
IRBuilder builder(F);

auto maxSize = (unsigned)UINT16_MAX;
auto size = estimateBestNumElemsToSerialize(allocInst);
size = std::min(maxSize, size);

// Should not create HBCAllocObjectFromBufferInst.
if (size == 0) {
return lowerAlloc(allocInst);
}

// Replace AllocObjectLiteral with HBCAllocObjectFromBufferInst
builder.setLocation(allocInst->getLocation());
builder.setCurrentSourceLevelScope(allocInst->getSourceLevelScope());
builder.setInsertionPointAfter(allocInst);
HBCAllocObjectFromBufferInst::ObjectPropertyMap propMap;

unsigned i = 0;
for (; i < size; i++) {
Literal *key = allocInst->getKey(i);
Value *value = allocInst->getValue(i);
Literal *propLiteral = nullptr;
// Property name can be either a LiteralNumber or a LiteralString.
if (auto *LN = llvh::dyn_cast<LiteralNumber>(key)) {
assert(
LN->convertToArrayIndex() &&
"LiteralNumber can be a property name only if it can be converted to array index.");
propLiteral = LN;
} else {
propLiteral = cast<LiteralString>(key);
}

if (isSerializableLiteral(value)) {
propMap.push_back(std::pair<Literal *, Literal *>(
propLiteral, llvh::cast<Literal>(value)));
} else if (llvh::isa<LiteralString>(propLiteral)) {
// LiteralString key with undefined / non-constant value.
propMap.push_back(std::pair<Literal *, Literal *>(
propLiteral, builder.getLiteralNull()));
builder.createStorePropertyInst(value, allocInst, key);
} else {
// LiteralNumber key with undefined / non-constant value.
// No need to put Null in the buffer, as numeric properties can
// be added in any order.
builder.createStoreOwnPropertyInst(
value, allocInst, key, IRBuilder::PropEnumerable::Yes);
}
}

// Handle properties beyond best num of properties or that cannot fit in
// maxSize.
for (; i < allocInst->getKeyValuePairCount(); i++) {
Literal *key = allocInst->getKey(i);
Value *value = allocInst->getValue(i);
builder.createStoreNewOwnPropertyInst(
value, allocInst, key, IRBuilder::PropEnumerable::Yes);
}

// Emit HBCAllocObjectFromBufferInst.
// First, we reset insertion location.
builder.setLocation(allocInst->getLocation());
builder.setCurrentSourceLevelScope(allocInst->getSourceLevelScope());
builder.setInsertionPoint(allocInst);
auto *alloc = builder.createHBCAllocObjectFromBufferInst(
propMap, allocInst->getKeyValuePairCount());
allocInst->replaceAllUsesWith(alloc);
allocInst->eraseFromParent();

return true;
}

bool LowerStoreInstrs::runOnFunction(Function *F) {
IRBuilder builder(F);
IRBuilder::InstructionDestroyer destroyer;
Expand Down Expand Up @@ -661,11 +509,6 @@ bool LowerNumericProperties::runOnFunction(Function *F) {
} else if (llvh::isa<StoreGetterSetterInst>(&Inst)) {
changed |= stringToNumericProperty(
builder, Inst, StoreGetterSetterInst::PropertyIdx);
} else if (llvh::isa<AllocObjectLiteralInst>(&Inst)) {
auto allocInst = cast<AllocObjectLiteralInst>(&Inst);
for (unsigned i = 0; i < allocInst->getKeyValuePairCount(); i++) {
changed |= stringToNumericProperty(builder, Inst, i * 2);
}
}
}
}
Expand Down
7 changes: 0 additions & 7 deletions lib/IR/IRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -990,13 +990,6 @@ HBCAllocObjectFromBufferInst *IRBuilder::createHBCAllocObjectFromBufferInst(
return inst;
}

AllocObjectLiteralInst *IRBuilder::createAllocObjectLiteralInst(
const AllocObjectLiteralInst::ObjectPropertyMap &propMap) {
auto *inst = new AllocObjectLiteralInst(propMap);
insert(inst);
return inst;
}

CompareBranchInst *IRBuilder::createCompareBranchInst(
Value *left,
Value *right,
Expand Down
7 changes: 0 additions & 7 deletions lib/IR/IRVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,13 +837,6 @@ void Verifier::visitHBCAllocObjectFromBufferInst(
"Cannot allocate an empty HBCAllocObjectFromBufferInst");
}

void Verifier::visitAllocObjectLiteralInst(
const hermes::AllocObjectLiteralInst &Inst) {
Assert(
Inst.getKeyValuePairCount() > 0,
"Cannot allocate an empty AllocObjectLiteralInst");
}

void Verifier::visitHBCGetGlobalObjectInst(const HBCGetGlobalObjectInst &Inst) {
// Nothing to verify at this point.
}
Expand Down
1 change: 0 additions & 1 deletion test/BCGen/HBC/own_properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

// Test that StoreNewOwnPropertyInst is lowered to StoreOwnPropertyInst when
// the property name is a valid array index.
// We use a computed key to avoid emitting AllocObjectLiteral.

function foo() {
return {a: 1, "10": 2, 11: 3, "999999999999999999999999": 4, ['42']: 5};
Expand Down
1 change: 0 additions & 1 deletion test/IRGen/hbc_object_literals-lowering.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

// RUN: %hermes --target=HBC -dump-lir -O %s | %FileCheckOrRegen %s --match-full-lines --check-prefix=IRGEN

// LowerNumericProperties should handle AllocObjectLiteral.
function emitAllocObjectLiteral(func) {
return {a: 1, b: 2, c: 3, d: 4, 5: 5, '6': 6};
}
Expand Down
Loading

0 comments on commit 4203296

Please sign in to comment.