| Index: src/compiler/typer.cc
|
| diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
|
| index 2430d40e00a5df787f9f1a0b4f737144af17e2ea..b3ea7ffa03fac4dc7ad1bfaa9568adab3bad11aa 100644
|
| --- a/src/compiler/typer.cc
|
| +++ b/src/compiler/typer.cc
|
| @@ -7,6 +7,7 @@
|
| #include "src/base/flags.h"
|
| #include "src/base/lazy-instance.h"
|
| #include "src/bootstrapper.h"
|
| +#include "src/compilation-dependencies.h"
|
| #include "src/compiler/common-operator.h"
|
| #include "src/compiler/graph-reducer.h"
|
| #include "src/compiler/js-operator.h"
|
| @@ -37,9 +38,13 @@ class Typer::Decorator final : public GraphDecorator {
|
| };
|
|
|
|
|
| -Typer::Typer(Isolate* isolate, Graph* graph, Type::FunctionType* function_type)
|
| +Typer::Typer(Isolate* isolate, Graph* graph, Flags flags,
|
| + CompilationDependencies* dependencies,
|
| + Type::FunctionType* function_type)
|
| : isolate_(isolate),
|
| graph_(graph),
|
| + flags_(flags),
|
| + dependencies_(dependencies),
|
| function_type_(function_type),
|
| decorator_(nullptr),
|
| cache_(kCache.Get()) {
|
| @@ -204,6 +209,10 @@ class Typer::Visitor : public Reducer {
|
| Zone* zone() { return typer_->zone(); }
|
| Isolate* isolate() { return typer_->isolate(); }
|
| Graph* graph() { return typer_->graph(); }
|
| + Typer::Flags flags() const { return typer_->flags(); }
|
| + CompilationDependencies* dependencies() const {
|
| + return typer_->dependencies();
|
| + }
|
|
|
| void SetWeakened(NodeId node_id) { weakened_nodes_.insert(node_id); }
|
| bool IsWeakened(NodeId node_id) {
|
| @@ -252,6 +261,8 @@ class Typer::Visitor : public Reducer {
|
| static Type* JSLoadPropertyTyper(Type*, Type*, Typer*);
|
| static Type* JSCallFunctionTyper(Type*, Typer*);
|
|
|
| + static Type* ReferenceEqualTyper(Type*, Type*, Typer*);
|
| +
|
| Reduction UpdateType(Node* node, Type* current) {
|
| if (NodeProperties::IsTyped(node)) {
|
| // Widen the type of a previously typed node.
|
| @@ -1575,8 +1586,17 @@ Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
|
| }
|
|
|
|
|
| +// static
|
| +Type* Typer::Visitor::ReferenceEqualTyper(Type* lhs, Type* rhs, Typer* t) {
|
| + if (lhs->IsConstant() && rhs->Is(lhs)) {
|
| + return t->singleton_true_;
|
| + }
|
| + return Type::Boolean();
|
| +}
|
| +
|
| +
|
| Type* Typer::Visitor::TypeReferenceEqual(Node* node) {
|
| - return Type::Boolean(zone());
|
| + return TypeBinaryOp(node, ReferenceEqualTyper);
|
| }
|
|
|
|
|
| @@ -1666,8 +1686,53 @@ Type* Typer::Visitor::TypeChangeBitToBool(Node* node) {
|
| Type* Typer::Visitor::TypeAllocate(Node* node) { return Type::TaggedPointer(); }
|
|
|
|
|
| +namespace {
|
| +
|
| +MaybeHandle<Map> GetStableMapFromObjectType(Type* object_type) {
|
| + if (object_type->IsConstant() &&
|
| + object_type->AsConstant()->Value()->IsHeapObject()) {
|
| + Handle<Map> object_map(
|
| + Handle<HeapObject>::cast(object_type->AsConstant()->Value())->map());
|
| + if (object_map->is_stable()) return object_map;
|
| + } else if (object_type->IsClass()) {
|
| + Handle<Map> object_map = object_type->AsClass()->Map();
|
| + if (object_map->is_stable()) return object_map;
|
| + }
|
| + return MaybeHandle<Map>();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +
|
| Type* Typer::Visitor::TypeLoadField(Node* node) {
|
| - return FieldAccessOf(node->op()).type;
|
| + FieldAccess const& access = FieldAccessOf(node->op());
|
| + if (access.base_is_tagged == kTaggedBase &&
|
| + access.offset == HeapObject::kMapOffset) {
|
| + // The type of LoadField[Map](o) is Constant(map) if map is stable and
|
| + // either
|
| + // (a) o has type Constant(object) and map == object->map, or
|
| + // (b) o has type Class(map),
|
| + // and either
|
| + // (1) map cannot transition further, or
|
| + // (2) deoptimization is enabled and we can add a code dependency on the
|
| + // stability of map (to guard the Constant type information).
|
| + Type* const object = Operand(node, 0);
|
| + if (object->Is(Type::None())) return Type::None();
|
| + Handle<Map> object_map;
|
| + if (GetStableMapFromObjectType(object).ToHandle(&object_map)) {
|
| + if (object_map->CanTransition()) {
|
| + if (flags() & kDeoptimizationEnabled) {
|
| + dependencies()->AssumeMapStable(object_map);
|
| + } else {
|
| + return access.type;
|
| + }
|
| + }
|
| + Type* object_map_type = Type::Constant(object_map, zone());
|
| + DCHECK(object_map_type->Is(access.type));
|
| + return object_map_type;
|
| + }
|
| + }
|
| + return access.type;
|
| }
|
|
|
|
|
|
|