ByteCode: Faster eval in getLocation, add safety for double side-effects
Change-Id: I4d1a102264d8c97bf9120c3891d569ef96a92922 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/222782 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
62392726b7
commit
8676929c0a
@ -213,7 +213,6 @@ int ByteCodeGenerator::getLocation(const Variable& var) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Elide Add 0 and Mul 1 sequences
|
|
||||||
int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
|
int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* storage) {
|
||||||
switch (expr.fKind) {
|
switch (expr.fKind) {
|
||||||
case Expression::kFieldAccess_Kind: {
|
case Expression::kFieldAccess_Kind: {
|
||||||
@ -224,9 +223,11 @@ int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* st
|
|||||||
offset += SlotCount(*f.fBase->fType.fields()[i].fType);
|
offset += SlotCount(*f.fBase->fType.fields()[i].fType);
|
||||||
}
|
}
|
||||||
if (baseAddr < 0) {
|
if (baseAddr < 0) {
|
||||||
|
if (offset != 0) {
|
||||||
this->write(ByteCodeInstruction::kPushImmediate);
|
this->write(ByteCodeInstruction::kPushImmediate);
|
||||||
this->write32(offset);
|
this->write32(offset);
|
||||||
this->write(ByteCodeInstruction::kAddI);
|
this->write(ByteCodeInstruction::kAddI);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
return baseAddr + offset;
|
return baseAddr + offset;
|
||||||
@ -239,15 +240,35 @@ int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* st
|
|||||||
if (i.fIndex->isConstant()) {
|
if (i.fIndex->isConstant()) {
|
||||||
offset = i.fIndex->getConstantInt() * stride;
|
offset = i.fIndex->getConstantInt() * stride;
|
||||||
} else {
|
} else {
|
||||||
|
if (i.fIndex->hasSideEffects()) {
|
||||||
|
// Having a side-effect in an indexer is technically safe for an rvalue,
|
||||||
|
// but with lvalues we have to evaluate the indexer twice, so make it an error.
|
||||||
|
fErrors.error(i.fIndex->fOffset,
|
||||||
|
"Index expressions with side-effects not supported in byte code.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
this->writeExpression(*i.fIndex);
|
this->writeExpression(*i.fIndex);
|
||||||
|
if (stride != 1) {
|
||||||
this->write(ByteCodeInstruction::kPushImmediate);
|
this->write(ByteCodeInstruction::kPushImmediate);
|
||||||
this->write32(stride);
|
this->write32(stride);
|
||||||
this->write(ByteCodeInstruction::kMultiplyI);
|
this->write(ByteCodeInstruction::kMultiplyI);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
int baseAddr = this->getLocation(*i.fBase, storage);
|
int baseAddr = this->getLocation(*i.fBase, storage);
|
||||||
|
|
||||||
|
// Are both components known statically?
|
||||||
if (baseAddr >= 0 && offset >= 0) {
|
if (baseAddr >= 0 && offset >= 0) {
|
||||||
return baseAddr + offset;
|
return baseAddr + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At least one component is dynamic (and on the stack).
|
||||||
|
|
||||||
|
// If the other component is zero, we're done
|
||||||
|
if (baseAddr == 0 || offset == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the non-dynamic component (if any) to the stack, then add the two
|
||||||
if (baseAddr >= 0) {
|
if (baseAddr >= 0) {
|
||||||
this->write(ByteCodeInstruction::kPushImmediate);
|
this->write(ByteCodeInstruction::kPushImmediate);
|
||||||
this->write32(baseAddr);
|
this->write32(baseAddr);
|
||||||
@ -265,9 +286,11 @@ int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* st
|
|||||||
int baseAddr = this->getLocation(*s.fBase, storage);
|
int baseAddr = this->getLocation(*s.fBase, storage);
|
||||||
int offset = s.fComponents[0];
|
int offset = s.fComponents[0];
|
||||||
if (baseAddr < 0) {
|
if (baseAddr < 0) {
|
||||||
|
if (offset != 0) {
|
||||||
this->write(ByteCodeInstruction::kPushImmediate);
|
this->write(ByteCodeInstruction::kPushImmediate);
|
||||||
this->write32(offset);
|
this->write32(offset);
|
||||||
this->write(ByteCodeInstruction::kAddI);
|
this->write(ByteCodeInstruction::kAddI);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
return baseAddr + offset;
|
return baseAddr + offset;
|
||||||
|
Loading…
Reference in New Issue
Block a user