[wasm-backend] Implement more comparison features.

This implements various small features needed for DeltaBlue:
- Comparison between two references
- Comparison between a reference and a literal null
- Assigning the result of a comparison to a bool variable
- Negating a bool
- Using a bool variable in a condition
- Mentioning dynamic (directly or indirectly)

Change-Id: I74c11cb180eb59e4bea66b751eafa59908325b2e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166623
Reviewed-by: Tess Strickland <sstrickl@google.com>
This commit is contained in:
Aske Simon Christensen 2020-10-09 12:19:45 +00:00
parent 5fdd324746
commit 4581081f22
4 changed files with 71 additions and 8 deletions

View file

@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
#include "vm/compiler/aot/wasm_codegen.h"
#include "vm/object_store.h"
#define Z (zone_)
#define M (module_builder_)
@ -191,8 +192,13 @@ void WasmCodegen::GenerateClassLayoutsAndRtts() {
}
WasmClassInfo& WasmCodegen::GetWasmClassInfo(const Class& klass) {
// Treat dynamic as Object.
Class& klass2 = Class::Handle(klass.raw());
if (klass.IsDynamicClass()) {
klass2 = Thread::Current()->isolate()->object_store()->object_class();
}
pair<const Class*, WasmClassInfo>* const pair =
class_to_wasm_class_info_.Lookup(&klass);
class_to_wasm_class_info_.Lookup(&klass2);
// At this point all classes should have been hoisted.
// If this is not true, exit with an error even in non-debug builds.
if (pair == nullptr) {

View file

@ -201,6 +201,15 @@ void WasmTranslator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) {
VisitBinaryIntegerOp(instr);
}
void WasmTranslator::VisitBooleanNegate(BooleanNegateInstr* instr) {
PushValue(instr->value()->definition(),
AbstractType::Handle(AbstractType::null()));
wasm_scope_->AddI32Constant(1);
wasm_scope_->AddIntOp(wasm::IntOp::IntegerKind::kI32,
wasm::IntOp::OpKind::kXor);
PopValue(instr);
}
void WasmTranslator::VisitParameter(ParameterInstr* instr) {
// If the parameter is not the This parameter of a method, then just map
// the parameter definition to the corresponding Wasm local of type kParam.
@ -370,6 +379,21 @@ void WasmTranslator::VisitStoreInstanceField(StoreInstanceFieldInstr* instr) {
wasm_scope_->AddStructSet(wasm_struct, wasm_field);
}
void WasmTranslator::VisitEqualityCompare(EqualityCompareInstr* instr) {
PushEvalCondition(instr, /*negated=*/false);
PopValue(instr);
}
void WasmTranslator::VisitStrictCompare(StrictCompareInstr* instr) {
PushEvalCondition(instr, /*negated=*/false);
PopValue(instr);
}
void WasmTranslator::VisitRelationalOp(RelationalOpInstr* instr) {
PushEvalCondition(instr, /*negated=*/false);
PopValue(instr);
}
intptr_t WasmTranslator::GetFallthroughPredecessorIndex(
BlockEntryInstr* target) {
intptr_t block_number = target->postorder_number();
@ -582,8 +606,34 @@ void WasmTranslator::PushEvalCondition(ComparisonInstr* comp, bool negated) {
wasm_scope_->AddIntOp(wasm::IntOp::IntegerKind::kI64, op_kind);
} else if (auto strict_comp_op =
comp->AsStrictCompare()) { // General StrictCompare === !==
// TODO(askesc): Figure out the details.
UNIMPLEMENTED();
negated ^= comp->kind() == Token::Kind::kNE_STRICT;
if (IsBoolValue(comp->right())) {
if (auto const_instr = comp->right()->definition()->AsConstant()) {
const Object& value = const_instr->value();
const bool bool_value = Bool::Cast(value).value();
negated ^= !bool_value;
PushValue(comp->left()->definition(),
*comp->left()->Type()->ToAbstractType());
} else {
UNIMPLEMENTED();
}
} else {
// To support comparison with a null constant on the right-hand side, we
// use the type of the left-hand side as the type hint for both operands.
// Alternatively, we could allow null constants without type hint and use
// the Object type in that case (which should be fine for comparisons).
PushValue(comp->left()->definition(),
*comp->left()->Type()->ToAbstractType());
PushValue(comp->right()->definition(),
*comp->left()->Type()->ToAbstractType());
wasm_scope_->AddRefEq();
}
if (negated) {
wasm_scope_->AddI32Constant(1);
wasm_scope_->AddIntOp(wasm::IntOp::IntegerKind::kI32,
wasm::IntOp::OpKind::kXor);
}
}
}

View file

@ -54,6 +54,7 @@ class WasmTranslator : public FlowGraphVisitor {
virtual void VisitBinaryInt32Op(BinaryInt32OpInstr* instr);
virtual void VisitBinaryInt64Op(BinaryInt64OpInstr* instr);
virtual void VisitBinaryUint32Op(BinaryUint32OpInstr* instr);
virtual void VisitBooleanNegate(BooleanNegateInstr* instr);
virtual void VisitParameter(ParameterInstr* instr);
virtual void VisitStaticCall(StaticCallInstr* instr);
virtual void VisitDispatchTableCall(DispatchTableCallInstr* instr);
@ -61,6 +62,9 @@ class WasmTranslator : public FlowGraphVisitor {
virtual void VisitAllocateObject(AllocateObjectInstr* instr);
virtual void VisitLoadField(LoadFieldInstr* instr);
virtual void VisitStoreInstanceField(StoreInstanceFieldInstr* instr);
virtual void VisitEqualityCompare(EqualityCompareInstr* instr);
virtual void VisitStrictCompare(StrictCompareInstr* instr);
virtual void VisitRelationalOp(RelationalOpInstr* instr);
private:
// Traverse graph to find start locations of Wasm blocks.

View file

@ -37,7 +37,7 @@
* implementation.
*/
main() {
void main() {
new DeltaBlue().run();
}
@ -90,6 +90,7 @@ abstract class Constraint {
Constraint(this.planner, this.strength);
@pragma("vm:never-inline")
bool isSatisfied();
void markUnsatisfied();
void addToGraph();
@ -114,7 +115,7 @@ abstract class Constraint {
* there is one, or nil, if there isn't.
* Assume: I am not already satisfied.
*/
Constraint satisfy(mark) {
Constraint satisfy(int mark) {
chooseMethod(mark);
if (!isSatisfied()) {
if (strength == REQUIRED) {
@ -170,6 +171,7 @@ abstract class UnaryConstraint extends Constraint {
}
/// Returns true if this constraint is satisfied in the current solution.
@pragma("vm:never-inline")
bool isSatisfied() => satisfied;
void markInputs(int mark) {
@ -286,6 +288,7 @@ abstract class BinaryConstraint extends Constraint {
}
/// Answer true if this constraint is satisfied in the current solution.
@pragma("vm:never-inline")
bool isSatisfied() => direction != NONE;
/// Mark the input variable with the given mark.
@ -423,7 +426,7 @@ class Variable {
/// Removes all traces of c from this variable.
void removeConstraint(Constraint c) {
constraints.remove(c);
if (determinedBy == c) determinedBy = null;
if (identical(determinedBy, c)) determinedBy = null;
}
}
@ -739,7 +742,7 @@ class ConstraintList {
dummy.prev = dummy;
}
bool get isEmpty => dummy.next == dummy;
bool get isEmpty => identical(dummy.next, dummy);
void add(Constraint constraint) {
ConstraintListElement element = new ConstraintListElement(constraint);
@ -758,7 +761,7 @@ class ConstraintList {
void remove(Constraint constraint) {
for (var elem = dummy.next; elem != dummy; elem = elem.next) {
if (elem.value == constraint) {
if (identical(elem.value, constraint)) {
elem.remove();
return;
}