Commit c0a249c4 authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

[turbofan] Typer accesses js heap through the heap broker.

This moves all accesses from Typer to the broker. This is policed by
DisallowHandleDereferenceScope in Typer::Visitor::Reduce.

Bug: v8:7790
Change-Id: Ic37d029261b3302eedb902a3b2249834a5dd0512
Reviewed-on: https://chromium-review.googlesource.com/1095305
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53659}
parent e1ff9368
...@@ -39,10 +39,47 @@ HeapReferenceType JSHeapBroker::HeapReferenceTypeFromMap(Map* map) const { ...@@ -39,10 +39,47 @@ HeapReferenceType JSHeapBroker::HeapReferenceTypeFromMap(Map* map) const {
return HeapReferenceType(map->instance_type(), flags, oddball_type); return HeapReferenceType(map->instance_type(), flags, oddball_type);
} }
HeapReferenceType JSHeapBroker::HeapReferenceTypeForObject( HeapReference JSHeapBroker::HeapReferenceForObject(
Handle<HeapObject> object) const { Handle<Object> object) const {
AllowHandleDereference allow_handle_dereference; AllowHandleDereference allow_handle_dereference;
return HeapReferenceTypeFromMap(object->map()); Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
HeapReferenceType type = HeapReferenceTypeFromMap(heap_object->map());
return HeapReference(heap_object, type);
}
// static
base::Optional<int> JSHeapBroker::TryGetSmi(Handle<Object> object) {
AllowHandleDereference allow_handle_dereference;
if (!object->IsSmi()) return base::Optional<int>();
return Smi::cast(*object)->value();
}
#define HEAP_KIND_FUNCTIONS_DEF(Name) \
bool HeapReference::Is##Name() const { \
AllowHandleDereference allow_handle_dereference; \
return object_->Is##Name(); \
}
HEAP_BROKER_KIND_LIST(HEAP_KIND_FUNCTIONS_DEF)
#undef HEAP_KIND_FUNCTIONS_DEF
NumberHeapData HeapReference::AsNumber() const {
AllowHandleDereference allow_handle_dereference;
return NumberHeapData(object_->Number());
}
JSFunctionHeapData HeapReference::AsJSFunction() const {
AllowHandleDereference allow_handle_dereference;
return JSFunctionHeapData(Handle<JSFunction>::cast(object_));
}
bool JSFunctionHeapData::HasBuiltinFunctionId() const {
AllowHandleDereference allow_handle_dereference;
return function_->shared()->HasBuiltinFunctionId();
}
BuiltinFunctionId JSFunctionHeapData::GetBuiltinFunctionId() const {
AllowHandleDereference allow_handle_dereference;
return function_->shared()->builtin_function_id();
} }
} // namespace compiler } // namespace compiler
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_COMPILER_JS_HEAP_BROKER_H_ #define V8_COMPILER_JS_HEAP_BROKER_H_
#include "src/base/compiler-specific.h" #include "src/base/compiler-specific.h"
#include "src/base/optional.h"
#include "src/globals.h" #include "src/globals.h"
#include "src/objects.h" #include "src/objects.h"
...@@ -13,6 +14,32 @@ namespace v8 { ...@@ -13,6 +14,32 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
class JSFunctionHeapData {
public:
bool HasBuiltinFunctionId() const;
BuiltinFunctionId GetBuiltinFunctionId() const;
private:
friend class HeapReference;
explicit JSFunctionHeapData(Handle<JSFunction> function)
: function_(function) {}
Handle<JSFunction> const function_;
};
class NumberHeapData {
public:
double value() const { return value_; }
private:
friend class HeapReference;
explicit NumberHeapData(double value) : value_(value) {}
double const value_;
};
class HeapReferenceType { class HeapReferenceType {
public: public:
enum OddballType : uint8_t { kUnknown, kBoolean, kUndefined, kNull, kHole }; enum OddballType : uint8_t { kUnknown, kBoolean, kUndefined, kNull, kHole };
...@@ -39,6 +66,38 @@ class HeapReferenceType { ...@@ -39,6 +66,38 @@ class HeapReferenceType {
Flags const flags_; Flags const flags_;
}; };
#define HEAP_BROKER_DATA_LIST(V) \
V(JSFunction) \
V(Number)
#define HEAP_BROKER_KIND_LIST(V) \
HEAP_BROKER_DATA_LIST(V) \
V(String) \
V(InternalizedString)
class HeapReference {
public:
#define HEAP_IS_METHOD_DECL(Name) bool Is##Name() const;
HEAP_BROKER_KIND_LIST(HEAP_IS_METHOD_DECL)
#undef HEAP_IS_METHOD_DECL
#define HEAP_AS_METHOD_DECL(Name) Name##HeapData As##Name() const;
HEAP_BROKER_DATA_LIST(HEAP_AS_METHOD_DECL)
#undef HEAP_AS_METHOD_DECL
const HeapReferenceType& type() const { return type_; }
Handle<HeapObject> value() const { return object_; }
private:
friend class JSHeapBroker;
HeapReference(Handle<HeapObject> object, const HeapReferenceType& type)
: object_(object), type_(type) {}
Handle<HeapObject> const object_;
HeapReferenceType const type_;
};
class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) { class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
public: public:
JSHeapBroker(Isolate* isolate); JSHeapBroker(Isolate* isolate);
...@@ -47,7 +106,9 @@ class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -47,7 +106,9 @@ class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
return HeapReferenceTypeFromMap(*map); return HeapReferenceTypeFromMap(*map);
} }
HeapReferenceType HeapReferenceTypeForObject(Handle<HeapObject> object) const; HeapReference HeapReferenceForObject(Handle<Object> object) const;
static base::Optional<int> TryGetSmi(Handle<Object> object);
private: private:
HeapReferenceType HeapReferenceTypeFromMap(Map* map) const; HeapReferenceType HeapReferenceTypeFromMap(Map* map) const;
......
...@@ -87,7 +87,9 @@ namespace { ...@@ -87,7 +87,9 @@ namespace {
MaybeHandle<Map> GetStableMapFromObjectType(Type object_type) { MaybeHandle<Map> GetStableMapFromObjectType(Type object_type) {
if (object_type.IsHeapConstant()) { if (object_type.IsHeapConstant()) {
Handle<Map> object_map(object_type.AsHeapConstant()->Value()->map()); Handle<HeapObject> object =
Handle<HeapObject>::cast(object_type.AsHeapConstant()->Value());
Handle<Map> object_map(object->map());
if (object_map->is_stable()) return object_map; if (object_map->is_stable()) return object_map;
} }
return MaybeHandle<Map>(); return MaybeHandle<Map>();
......
...@@ -64,6 +64,7 @@ class Typer::Visitor : public Reducer { ...@@ -64,6 +64,7 @@ class Typer::Visitor : public Reducer {
const char* reducer_name() const override { return "Typer"; } const char* reducer_name() const override { return "Typer"; }
Reduction Reduce(Node* node) override { Reduction Reduce(Node* node) override {
DisallowHandleDereference disallow_handle_dereference;
if (node->op()->ValueOutputCount() == 0) return NoChange(); if (node->op()->ValueOutputCount() == 0) return NoChange();
switch (node->opcode()) { switch (node->opcode()) {
#define DECLARE_CASE(x) \ #define DECLARE_CASE(x) \
...@@ -1400,11 +1401,14 @@ Type Typer::Visitor::TypeJSObjectIsArray(Node* node) { return Type::Boolean(); } ...@@ -1400,11 +1401,14 @@ Type Typer::Visitor::TypeJSObjectIsArray(Node* node) { return Type::Boolean(); }
Type Typer::Visitor::TypeDateNow(Node* node) { return Type::Number(); } Type Typer::Visitor::TypeDateNow(Node* node) { return Type::Number(); }
Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) { Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
if (fun.IsHeapConstant() && fun.AsHeapConstant()->Value()->IsJSFunction()) { if (!fun.IsHeapConstant() || !fun.AsHeapConstant()->Ref().IsJSFunction()) {
Handle<JSFunction> function = return Type::NonInternal();
Handle<JSFunction>::cast(fun.AsHeapConstant()->Value()); }
if (function->shared()->HasBuiltinFunctionId()) { JSFunctionHeapData function = fun.AsHeapConstant()->Ref().AsJSFunction();
switch (function->shared()->builtin_function_id()) { if (!function.HasBuiltinFunctionId()) {
return Type::NonInternal();
}
switch (function.GetBuiltinFunctionId()) {
case kMathRandom: case kMathRandom:
return Type::PlainNumber(); return Type::PlainNumber();
case kMathFloor: case kMathFloor:
...@@ -1667,11 +1671,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) { ...@@ -1667,11 +1671,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
case kWeakSetHas: case kWeakSetHas:
return Type::Boolean(); return Type::Boolean();
default: default:
break;
}
}
}
return Type::NonInternal(); return Type::NonInternal();
}
} }
Type Typer::Visitor::TypeJSCallForwardVarargs(Node* node) { Type Typer::Visitor::TypeJSCallForwardVarargs(Node* node) {
......
...@@ -331,18 +331,9 @@ Type::bitset BitsetType::Lub(HeapReferenceType const& type) { ...@@ -331,18 +331,9 @@ Type::bitset BitsetType::Lub(HeapReferenceType const& type) {
UNREACHABLE(); UNREACHABLE();
} }
Type::bitset BitsetType::Lub(const JSHeapBroker* js_heap_broker,
Handle<HeapObject> value) {
DisallowHeapAllocation no_allocation;
if (value->IsNumber()) {
return Lub(value->Number());
}
return Lub(js_heap_broker->HeapReferenceTypeForObject(value));
}
Type::bitset BitsetType::Lub(double value) { Type::bitset BitsetType::Lub(double value) {
DisallowHeapAllocation no_allocation; DisallowHeapAllocation no_allocation;
if (i::IsMinusZero(value)) return kMinusZero; if (IsMinusZero(value)) return kMinusZero;
if (std::isnan(value)) return kNaN; if (std::isnan(value)) return kNaN;
if (IsUint32Double(value) || IsInt32Double(value)) return Lub(value, value); if (IsUint32Double(value) || IsInt32Double(value)) return Lub(value, value);
return kOtherNumber; return kOtherNumber;
...@@ -450,15 +441,12 @@ double BitsetType::Max(bitset bits) { ...@@ -450,15 +441,12 @@ double BitsetType::Max(bitset bits) {
bool OtherNumberConstantType::IsOtherNumberConstant(double value) { bool OtherNumberConstantType::IsOtherNumberConstant(double value) {
// Not an integer, not NaN, and not -0. // Not an integer, not NaN, and not -0.
return !std::isnan(value) && !RangeType::IsInteger(value) && return !std::isnan(value) && !RangeType::IsInteger(value) &&
!i::IsMinusZero(value); !IsMinusZero(value);
} }
HeapConstantType::HeapConstantType(BitsetType::bitset bitset, HeapConstantType::HeapConstantType(BitsetType::bitset bitset,
i::Handle<i::HeapObject> object) const HeapReference& heap_ref)
: TypeBase(kHeapConstant), bitset_(bitset), object_(object) { : TypeBase(kHeapConstant), bitset_(bitset), heap_ref_(heap_ref) {}
DCHECK(!object->IsHeapNumber());
DCHECK_IMPLIES(object->IsString(), object->IsInternalizedString());
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Predicates. // Predicates.
...@@ -804,7 +792,7 @@ Type Type::NormalizeRangeAndBitset(Type range, bitset* bits, Zone* zone) { ...@@ -804,7 +792,7 @@ Type Type::NormalizeRangeAndBitset(Type range, bitset* bits, Zone* zone) {
Type Type::NewConstant(double value, Zone* zone) { Type Type::NewConstant(double value, Zone* zone) {
if (RangeType::IsInteger(value)) { if (RangeType::IsInteger(value)) {
return Range(value, value, zone); return Range(value, value, zone);
} else if (i::IsMinusZero(value)) { } else if (IsMinusZero(value)) {
return Type::MinusZero(); return Type::MinusZero();
} else if (std::isnan(value)) { } else if (std::isnan(value)) {
return Type::NaN(); return Type::NaN();
...@@ -816,12 +804,20 @@ Type Type::NewConstant(double value, Zone* zone) { ...@@ -816,12 +804,20 @@ Type Type::NewConstant(double value, Zone* zone) {
Type Type::NewConstant(const JSHeapBroker* js_heap_broker, Type Type::NewConstant(const JSHeapBroker* js_heap_broker,
Handle<i::Object> value, Zone* zone) { Handle<i::Object> value, Zone* zone) {
if (value->IsNumber()) { auto maybe_smi = JSHeapBroker::TryGetSmi(value);
return NewConstant(value->Number(), zone); if (maybe_smi.has_value()) {
} else if (value->IsString() && !value->IsInternalizedString()) { return NewConstant(static_cast<double>(maybe_smi.value()), zone);
}
HeapReference heap_ref = js_heap_broker->HeapReferenceForObject(value);
if (heap_ref.IsNumber()) {
return NewConstant(heap_ref.AsNumber().value(), zone);
}
if (heap_ref.IsString() && !heap_ref.IsInternalizedString()) {
return Type::String(); return Type::String();
} }
return HeapConstant(js_heap_broker, Handle<HeapObject>::cast(value), zone); return HeapConstant(js_heap_broker, value, zone);
} }
Type Type::Union(Type type1, Type type2, Zone* zone) { Type Type::Union(Type type1, Type type2, Zone* zone) {
...@@ -1025,11 +1021,11 @@ void BitsetType::Print(bitset bits) { ...@@ -1025,11 +1021,11 @@ void BitsetType::Print(bitset bits) {
#endif #endif
BitsetType::bitset BitsetType::SignedSmall() { BitsetType::bitset BitsetType::SignedSmall() {
return i::SmiValuesAre31Bits() ? kSigned31 : kSigned32; return SmiValuesAre31Bits() ? kSigned31 : kSigned32;
} }
BitsetType::bitset BitsetType::UnsignedSmall() { BitsetType::bitset BitsetType::UnsignedSmall() {
return i::SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31; return SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31;
} }
// static // static
...@@ -1048,8 +1044,9 @@ Type Type::OtherNumberConstant(double value, Zone* zone) { ...@@ -1048,8 +1044,9 @@ Type Type::OtherNumberConstant(double value, Zone* zone) {
// static // static
Type Type::HeapConstant(const JSHeapBroker* js_heap_broker, Type Type::HeapConstant(const JSHeapBroker* js_heap_broker,
Handle<HeapObject> value, Zone* zone) { Handle<i::Object> value, Zone* zone) {
return FromTypeBase(HeapConstantType::New(js_heap_broker, value, zone)); return FromTypeBase(HeapConstantType::New(
js_heap_broker->HeapReferenceForObject(value), zone));
} }
// static // static
......
...@@ -252,8 +252,6 @@ class V8_EXPORT_PRIVATE BitsetType { ...@@ -252,8 +252,6 @@ class V8_EXPORT_PRIVATE BitsetType {
static bitset Glb(double min, double max); static bitset Glb(double min, double max);
static bitset Lub(HeapReferenceType const& type); static bitset Lub(HeapReferenceType const& type);
static bitset Lub(const JSHeapBroker* js_heap_broker,
Handle<HeapObject> value);
static bitset Lub(double value); static bitset Lub(double value);
static bitset Lub(double min, double max); static bitset Lub(double min, double max);
static bitset ExpandInternals(bitset bits); static bitset ExpandInternals(bitset bits);
...@@ -315,7 +313,7 @@ class RangeType : public TypeBase { ...@@ -315,7 +313,7 @@ class RangeType : public TypeBase {
double Max() const { return limits_.max; } double Max() const { return limits_.max; }
static bool IsInteger(double x) { static bool IsInteger(double x) {
return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. return nearbyint(x) == x && !IsMinusZero(x); // Allows for infinities.
} }
private: private:
...@@ -364,7 +362,7 @@ class V8_EXPORT_PRIVATE Type { ...@@ -364,7 +362,7 @@ class V8_EXPORT_PRIVATE Type {
static Type OtherNumberConstant(double value, Zone* zone); static Type OtherNumberConstant(double value, Zone* zone);
static Type HeapConstant(const JSHeapBroker* js_heap_broker, static Type HeapConstant(const JSHeapBroker* js_heap_broker,
Handle<HeapObject> value, Zone* zone); Handle<i::Object> value, Zone* zone);
static Type Range(double min, double max, Zone* zone); static Type Range(double min, double max, Zone* zone);
static Type Range(RangeType::Limits lims, Zone* zone); static Type Range(RangeType::Limits lims, Zone* zone);
static Type Tuple(Type first, Type second, Type third, Zone* zone); static Type Tuple(Type first, Type second, Type third, Zone* zone);
...@@ -536,25 +534,27 @@ class OtherNumberConstantType : public TypeBase { ...@@ -536,25 +534,27 @@ class OtherNumberConstantType : public TypeBase {
class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) { class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) {
public: public:
i::Handle<i::HeapObject> Value() const { return object_; } Handle<HeapObject> Value() const { return heap_ref_.value(); }
const HeapReference& Ref() const { return heap_ref_; }
private: private:
friend class Type; friend class Type;
friend class BitsetType; friend class BitsetType;
static HeapConstantType* New(const JSHeapBroker* js_heap_broker, static HeapConstantType* New(const HeapReference& heap_ref, Zone* zone) {
i::Handle<i::HeapObject> value, Zone* zone) { DCHECK(!heap_ref.IsNumber());
BitsetType::bitset bitset = BitsetType::Lub(js_heap_broker, value); DCHECK_IMPLIES(heap_ref.IsString(), heap_ref.IsInternalizedString());
BitsetType::bitset bitset = BitsetType::Lub(heap_ref.type());
return new (zone->New(sizeof(HeapConstantType))) return new (zone->New(sizeof(HeapConstantType)))
HeapConstantType(bitset, value); HeapConstantType(bitset, heap_ref);
} }
HeapConstantType(BitsetType::bitset bitset, i::Handle<i::HeapObject> object); HeapConstantType(BitsetType::bitset bitset, const HeapReference& heap_ref);
BitsetType::bitset Lub() const { return bitset_; } BitsetType::bitset Lub() const { return bitset_; }
BitsetType::bitset bitset_; BitsetType::bitset bitset_;
Handle<i::HeapObject> object_; HeapReference heap_ref_;
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -583,7 +583,7 @@ class StructuralType : public TypeBase { ...@@ -583,7 +583,7 @@ class StructuralType : public TypeBase {
length_ = length; length_ = length;
} }
StructuralType(Kind kind, int length, i::Zone* zone) StructuralType(Kind kind, int length, Zone* zone)
: TypeBase(kind), length_(length) { : TypeBase(kind), length_(length) {
elements_ = reinterpret_cast<Type*>(zone->New(sizeof(Type) * length)); elements_ = reinterpret_cast<Type*>(zone->New(sizeof(Type) * length));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment