mirror of
https://github.com/dart-lang/sdk
synced 2024-09-30 04:48:37 +00:00
[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:
parent
5fdd324746
commit
4581081f22
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
13
third_party/benchmarks/DeltaBlueSimplified.dart
vendored
13
third_party/benchmarks/DeltaBlueSimplified.dart
vendored
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue