Replace C++ bitfields with our own BitFields

Shave this yak from orbit, it's the only way to be sure.

BUG=chromium:427616
LOG=n
R=svenpanne@chromium.org

Review URL: https://codereview.chromium.org/700963002

Cr-Commit-Position: refs/heads/master@{#25148}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25148 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 66430307
......@@ -61,9 +61,9 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const {
VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
: Expression(zone, position),
is_this_(var->is_this()),
is_assigned_(false),
is_resolved_(false),
bit_field_(IsThisField::encode(var->is_this()) |
IsAssignedField::encode(false) |
IsResolvedField::encode(false)),
variable_feedback_slot_(FeedbackVectorICSlot::Invalid()),
raw_name_(var->raw_name()),
interface_(var->interface()) {
......@@ -74,9 +74,8 @@ VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
VariableProxy::VariableProxy(Zone* zone, const AstRawString* name, bool is_this,
Interface* interface, int position)
: Expression(zone, position),
is_this_(is_this),
is_assigned_(false),
is_resolved_(false),
bit_field_(IsThisField::encode(is_this) | IsAssignedField::encode(false) |
IsResolvedField::encode(false)),
variable_feedback_slot_(FeedbackVectorICSlot::Invalid()),
raw_name_(name),
interface_(interface) {}
......@@ -99,17 +98,17 @@ void VariableProxy::BindTo(Variable* var) {
Assignment::Assignment(Zone* zone, Token::Value op, Expression* target,
Expression* value, int pos)
: Expression(zone, pos),
is_uninitialized_(false),
key_type_(ELEMENT),
store_mode_(STANDARD_STORE),
op_(op),
bit_field_(IsUninitializedField::encode(false) |
KeyTypeField::encode(ELEMENT) |
StoreModeField::encode(STANDARD_STORE) |
TokenField::encode(op)),
target_(target),
value_(value),
binary_operation_(NULL) {}
Token::Value Assignment::binary_op() const {
switch (op_) {
switch (op()) {
case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
......
......@@ -359,11 +359,16 @@ class Expression : public AstNode {
void set_bounds(Bounds bounds) { bounds_ = bounds; }
// Whether the expression is parenthesized
bool is_parenthesized() const { return is_parenthesized_; }
bool is_multi_parenthesized() const { return is_multi_parenthesized_; }
bool is_parenthesized() const {
return IsParenthesizedField::decode(bit_field_);
}
bool is_multi_parenthesized() const {
return IsMultiParenthesizedField::decode(bit_field_);
}
void increase_parenthesization_level() {
is_multi_parenthesized_ = is_parenthesized_;
is_parenthesized_ = true;
bit_field_ =
IsMultiParenthesizedField::update(bit_field_, is_parenthesized());
bit_field_ = IsParenthesizedField::update(bit_field_, true);
}
// Type feedback information for assignments and properties.
......@@ -375,18 +380,20 @@ class Expression : public AstNode {
UNREACHABLE();
return NULL;
}
virtual KeyedAccessStoreMode GetStoreMode() {
virtual KeyedAccessStoreMode GetStoreMode() const {
UNREACHABLE();
return STANDARD_STORE;
}
virtual IcCheckType GetKeyType() {
virtual IcCheckType GetKeyType() const {
UNREACHABLE();
return ELEMENT;
}
// TODO(rossberg): this should move to its own AST node eventually.
virtual void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
byte to_boolean_types() const { return to_boolean_types_; }
byte to_boolean_types() const {
return ToBooleanTypesField::decode(bit_field_);
}
void set_base_id(int id) { base_id_ = id; }
static int num_ids() { return parent_num_ids() + 2; }
......@@ -398,10 +405,11 @@ class Expression : public AstNode {
: AstNode(pos),
base_id_(BailoutId::None().ToInt()),
bounds_(Bounds::Unbounded(zone)),
is_parenthesized_(false),
is_multi_parenthesized_(false) {}
bit_field_(0) {}
static int parent_num_ids() { return 0; }
void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
void set_to_boolean_types(byte types) {
bit_field_ = ToBooleanTypesField::update(bit_field_, types);
}
int base_id() const {
DCHECK(!BailoutId(base_id_).IsNone());
......@@ -413,9 +421,12 @@ class Expression : public AstNode {
int base_id_;
Bounds bounds_;
byte to_boolean_types_;
bool is_parenthesized_ : 1;
bool is_multi_parenthesized_ : 1;
class ToBooleanTypesField : public BitField16<byte, 0, 8> {};
class IsParenthesizedField : public BitField16<bool, 8, 1> {};
class IsMultiParenthesizedField : public BitField16<bool, 9, 1> {};
uint16_t bit_field_;
// Ends with 16-bit field; deriving classes in turn begin with
// 16-bit fields for optimum packing efficiency.
};
......@@ -1697,13 +1708,17 @@ class VariableProxy FINAL : public Expression {
var_ = v;
}
bool is_this() const { return is_this_; }
bool is_this() const { return IsThisField::decode(bit_field_); }
bool is_assigned() const { return is_assigned_; }
void set_is_assigned() { is_assigned_ = true; }
bool is_assigned() const { return IsAssignedField::decode(bit_field_); }
void set_is_assigned() {
bit_field_ = IsAssignedField::update(bit_field_, true);
}
bool is_resolved() const { return is_resolved_; }
void set_is_resolved() { is_resolved_ = true; }
bool is_resolved() const { return IsResolvedField::decode(bit_field_); }
void set_is_resolved() {
bit_field_ = IsResolvedField::update(bit_field_, true);
}
Interface* interface() const { return interface_; }
......@@ -1727,9 +1742,13 @@ class VariableProxy FINAL : public Expression {
VariableProxy(Zone* zone, const AstRawString* name, bool is_this,
Interface* interface, int position);
bool is_this_ : 1;
bool is_assigned_ : 1;
bool is_resolved_ : 1;
class IsThisField : public BitField8<bool, 0, 1> {};
class IsAssignedField : public BitField8<bool, 1, 1> {};
class IsResolvedField : public BitField8<bool, 2, 1> {};
// Start with 16-bit (or smaller) field, which should get packed together
// with Expression's trailing 16-bit field.
uint8_t bit_field_;
FeedbackVectorICSlot variable_feedback_slot_;
union {
const AstRawString* raw_name_; // if !is_resolved_
......@@ -1752,7 +1771,9 @@ class Property FINAL : public Expression {
BailoutId LoadId() const { return BailoutId(local_id(0)); }
TypeFeedbackId PropertyFeedbackId() { return TypeFeedbackId(local_id(1)); }
bool IsStringAccess() const { return is_string_access_; }
bool IsStringAccess() const {
return IsStringAccessField::decode(bit_field_);
}
// Type feedback information.
virtual bool IsMonomorphic() OVERRIDE {
......@@ -1761,21 +1782,29 @@ class Property FINAL : public Expression {
virtual SmallMapList* GetReceiverTypes() OVERRIDE {
return &receiver_types_;
}
virtual KeyedAccessStoreMode GetStoreMode() OVERRIDE {
virtual KeyedAccessStoreMode GetStoreMode() const OVERRIDE {
return STANDARD_STORE;
}
virtual IcCheckType GetKeyType() OVERRIDE {
virtual IcCheckType GetKeyType() const OVERRIDE {
// PROPERTY key types currently aren't implemented for KeyedLoadICs.
return ELEMENT;
}
bool IsUninitialized() { return !is_for_call_ && is_uninitialized_; }
bool HasNoTypeInformation() {
return is_uninitialized_;
bool IsUninitialized() const {
return !is_for_call() && HasNoTypeInformation();
}
bool HasNoTypeInformation() const {
return IsUninitializedField::decode(bit_field_);
}
void set_is_uninitialized(bool b) {
bit_field_ = IsUninitializedField::update(bit_field_, b);
}
void set_is_uninitialized(bool b) { is_uninitialized_ = b; }
void set_is_string_access(bool b) { is_string_access_ = b; }
void mark_for_call() { is_for_call_ = true; }
bool IsForCall() { return is_for_call_; }
void set_is_string_access(bool b) {
bit_field_ = IsStringAccessField::update(bit_field_, b);
}
void mark_for_call() {
bit_field_ = IsForCallField::update(bit_field_, true);
}
bool is_for_call() const { return IsForCallField::decode(bit_field_); }
bool IsSuperAccess() {
return obj()->IsSuperReference();
......@@ -1795,9 +1824,9 @@ class Property FINAL : public Expression {
protected:
Property(Zone* zone, Expression* obj, Expression* key, int pos)
: Expression(zone, pos),
is_for_call_(false),
is_uninitialized_(false),
is_string_access_(false),
bit_field_(IsForCallField::encode(false) |
IsUninitializedField::encode(false) |
IsStringAccessField::encode(false)),
property_feedback_slot_(FeedbackVectorICSlot::Invalid()),
obj_(obj),
key_(key) {}
......@@ -1806,9 +1835,10 @@ class Property FINAL : public Expression {
private:
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
bool is_for_call_ : 1;
bool is_uninitialized_ : 1;
bool is_string_access_ : 1;
class IsForCallField : public BitField8<bool, 0, 1> {};
class IsUninitializedField : public BitField8<bool, 1, 1> {};
class IsStringAccessField : public BitField8<bool, 2, 1> {};
uint8_t bit_field_;
FeedbackVectorICSlot property_feedback_slot_;
Expression* obj_;
Expression* key_;
......@@ -2120,10 +2150,10 @@ class CountOperation FINAL : public Expression {
public:
DECLARE_NODE_TYPE(CountOperation)
bool is_prefix() const { return is_prefix_; }
bool is_postfix() const { return !is_prefix_; }
bool is_prefix() const { return IsPrefixField::decode(bit_field_); }
bool is_postfix() const { return !is_prefix(); }
Token::Value op() const { return op_; }
Token::Value op() const { return TokenField::decode(bit_field_); }
Token::Value binary_op() {
return (op() == Token::INC) ? Token::ADD : Token::SUB;
}
......@@ -2136,13 +2166,19 @@ class CountOperation FINAL : public Expression {
virtual SmallMapList* GetReceiverTypes() OVERRIDE {
return &receiver_types_;
}
virtual IcCheckType GetKeyType() OVERRIDE { return key_type_; }
virtual KeyedAccessStoreMode GetStoreMode() OVERRIDE {
return store_mode_;
virtual IcCheckType GetKeyType() const OVERRIDE {
return KeyTypeField::decode(bit_field_);
}
virtual KeyedAccessStoreMode GetStoreMode() const OVERRIDE {
return StoreModeField::decode(bit_field_);
}
Type* type() const { return type_; }
void set_key_type(IcCheckType type) { key_type_ = type; }
void set_store_mode(KeyedAccessStoreMode mode) { store_mode_ = mode; }
void set_key_type(IcCheckType type) {
bit_field_ = KeyTypeField::update(bit_field_, type);
}
void set_store_mode(KeyedAccessStoreMode mode) {
bit_field_ = StoreModeField::update(bit_field_, mode);
}
void set_type(Type* type) { type_ = type; }
static int num_ids() { return parent_num_ids() + 3; }
......@@ -2158,21 +2194,25 @@ class CountOperation FINAL : public Expression {
CountOperation(Zone* zone, Token::Value op, bool is_prefix, Expression* expr,
int pos)
: Expression(zone, pos),
op_(op),
is_prefix_(is_prefix),
key_type_(ELEMENT),
store_mode_(STANDARD_STORE),
bit_field_(IsPrefixField::encode(is_prefix) |
KeyTypeField::encode(ELEMENT) |
StoreModeField::encode(STANDARD_STORE) |
TokenField::encode(op)),
type_(NULL),
expression_(expr) {}
static int parent_num_ids() { return Expression::num_ids(); }
private:
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
Token::Value op_;
bool is_prefix_ : 1;
IcCheckType key_type_ : 1;
KeyedAccessStoreMode store_mode_ : 5; // Windows treats as signed,
// must have extra bit.
class IsPrefixField : public BitField16<bool, 0, 1> {};
class KeyTypeField : public BitField16<IcCheckType, 1, 1> {};
class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 4> {};
class TokenField : public BitField16<Token::Value, 6, 8> {};
// Starts with 16-bit field, which should get packed together with
// Expression's trailing 16-bit field.
uint16_t bit_field_;
Type* type_;
Expression* expression_;
SmallMapList receiver_types_;
......@@ -2261,7 +2301,7 @@ class Assignment FINAL : public Expression {
Token::Value binary_op() const;
Token::Value op() const { return op_; }
Token::Value op() const { return TokenField::decode(bit_field_); }
Expression* target() const { return target_; }
Expression* value() const { return value_; }
BinaryOperation* binary_operation() const { return binary_operation_; }
......@@ -2277,20 +2317,30 @@ class Assignment FINAL : public Expression {
virtual bool IsMonomorphic() OVERRIDE {
return receiver_types_.length() == 1;
}
bool IsUninitialized() { return is_uninitialized_; }
bool IsUninitialized() const {
return IsUninitializedField::decode(bit_field_);
}
bool HasNoTypeInformation() {
return is_uninitialized_;
return IsUninitializedField::decode(bit_field_);
}
virtual SmallMapList* GetReceiverTypes() OVERRIDE {
return &receiver_types_;
}
virtual IcCheckType GetKeyType() OVERRIDE { return key_type_; }
virtual KeyedAccessStoreMode GetStoreMode() OVERRIDE {
return store_mode_;
virtual IcCheckType GetKeyType() const OVERRIDE {
return KeyTypeField::decode(bit_field_);
}
virtual KeyedAccessStoreMode GetStoreMode() const OVERRIDE {
return StoreModeField::decode(bit_field_);
}
void set_is_uninitialized(bool b) {
bit_field_ = IsUninitializedField::update(bit_field_, b);
}
void set_key_type(IcCheckType key_type) {
bit_field_ = KeyTypeField::update(bit_field_, key_type);
}
void set_store_mode(KeyedAccessStoreMode mode) {
bit_field_ = StoreModeField::update(bit_field_, mode);
}
void set_is_uninitialized(bool b) { is_uninitialized_ = b; }
void set_key_type(IcCheckType key_type) { key_type_ = key_type; }
void set_store_mode(KeyedAccessStoreMode mode) { store_mode_ = mode; }
protected:
Assignment(Zone* zone, Token::Value op, Expression* target, Expression* value,
......@@ -2299,7 +2349,7 @@ class Assignment FINAL : public Expression {
template <class Visitor>
void Init(AstNodeFactory<Visitor>* factory) {
DCHECK(Token::IsAssignmentOp(op_));
DCHECK(Token::IsAssignmentOp(op()));
if (is_compound()) {
binary_operation_ = factory->NewBinaryOperation(
binary_op(), target_, value_, position() + 1);
......@@ -2309,11 +2359,14 @@ class Assignment FINAL : public Expression {
private:
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
bool is_uninitialized_ : 1;
IcCheckType key_type_ : 1;
KeyedAccessStoreMode store_mode_ : 5; // Windows treats as signed,
// must have extra bit.
Token::Value op_;
class IsUninitializedField : public BitField16<bool, 0, 1> {};
class KeyTypeField : public BitField16<IcCheckType, 1, 1> {};
class StoreModeField : public BitField16<KeyedAccessStoreMode, 2, 4> {};
class TokenField : public BitField16<Token::Value, 6, 8> {};
// Starts with 16-bit field, which should get packed together with
// Expression's trailing 16-bit field.
uint16_t bit_field_;
Expression* target_;
Expression* value_;
BinaryOperation* binary_operation_;
......
......@@ -12,7 +12,7 @@ namespace internal {
HeapEntry* HeapGraphEdge::from() const {
return &snapshot()->entries()[from_index_];
return &snapshot()->entries()[from_index()];
}
......
......@@ -18,8 +18,7 @@ namespace internal {
HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to)
: type_(type),
from_index_(from),
: bit_field_(TypeField::encode(type) | FromIndexField::encode(from)),
to_index_(to),
name_(name) {
DCHECK(type == kContextVariable
......@@ -31,8 +30,7 @@ HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to)
HeapGraphEdge::HeapGraphEdge(Type type, int index, int from, int to)
: type_(type),
from_index_(from),
: bit_field_(TypeField::encode(type) | FromIndexField::encode(from)),
to_index_(to),
index_(index) {
DCHECK(type == kElement || type == kHidden);
......
......@@ -28,22 +28,18 @@ class HeapGraphEdge BASE_EMBEDDED {
kWeak = v8::HeapGraphEdge::kWeak
};
HeapGraphEdge() { }
HeapGraphEdge(Type type, const char* name, int from, int to);
HeapGraphEdge(Type type, int index, int from, int to);
void ReplaceToIndexWithEntry(HeapSnapshot* snapshot);
Type type() const { return static_cast<Type>(type_); }
Type type() const { return TypeField::decode(bit_field_); }
int index() const {
DCHECK(type_ == kElement || type_ == kHidden);
DCHECK(type() == kElement || type() == kHidden);
return index_;
}
const char* name() const {
DCHECK(type_ == kContextVariable
|| type_ == kProperty
|| type_ == kInternal
|| type_ == kShortcut
|| type_ == kWeak);
DCHECK(type() == kContextVariable || type() == kProperty ||
type() == kInternal || type() == kShortcut || type() == kWeak);
return name_;
}
INLINE(HeapEntry* from() const);
......@@ -51,9 +47,11 @@ class HeapGraphEdge BASE_EMBEDDED {
private:
INLINE(HeapSnapshot* snapshot() const);
int from_index() const { return FromIndexField::decode(bit_field_); }
unsigned type_ : 3;
int from_index_ : 29;
class TypeField : public BitField<Type, 0, 3> {};
class FromIndexField : public BitField<int, 3, 29> {};
uint32_t bit_field_;
union {
// During entries population |to_index_| is used for storing the index,
// afterwards it is replaced with a pointer to the entry.
......
......@@ -1789,7 +1789,7 @@ Range* HChange::InferRange(Zone* zone) {
Range* HConstant::InferRange(Zone* zone) {
if (has_int32_value_) {
if (HasInteger32Value()) {
Range* result = new(zone) Range(int32_value_, int32_value_);
result->set_can_be_minus_zero(false);
return result;
......@@ -2606,7 +2606,7 @@ std::ostream& HSimulate::PrintDataTo(std::ostream& os) const { // NOLINT
void HSimulate::ReplayEnvironment(HEnvironment* env) {
if (done_with_replay_) return;
if (is_done_with_replay()) return;
DCHECK(env != NULL);
env->set_ast_id(ast_id());
env->Drop(pop_count());
......@@ -2618,7 +2618,7 @@ void HSimulate::ReplayEnvironment(HEnvironment* env) {
env->Push(value);
}
}
done_with_replay_ = true;
set_done_with_replay();
}
......@@ -2674,36 +2674,41 @@ static bool IsInteger32(double value) {
HConstant::HConstant(Handle<Object> object, Representation r)
: HTemplateInstruction<0>(HType::FromValue(object)),
object_(Unique<Object>::CreateUninitialized(object)),
object_map_(Handle<Map>::null()),
has_stable_map_value_(false),
has_smi_value_(false),
has_int32_value_(false),
has_double_value_(false),
has_external_reference_value_(false),
is_not_in_new_space_(true),
boolean_value_(object->BooleanValue()),
is_undetectable_(false),
instance_type_(kUnknownInstanceType) {
: HTemplateInstruction<0>(HType::FromValue(object)),
object_(Unique<Object>::CreateUninitialized(object)),
object_map_(Handle<Map>::null()),
bit_field_(HasStableMapValueField::encode(false) |
HasSmiValueField::encode(false) |
HasInt32ValueField::encode(false) |
HasDoubleValueField::encode(false) |
HasExternalReferenceValueField::encode(false) |
IsNotInNewSpaceField::encode(true) |
BooleanValueField::encode(object->BooleanValue()) |
IsUndetectableField::encode(false) |
InstanceTypeField::encode(kUnknownInstanceType)) {
if (object->IsHeapObject()) {
Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
Isolate* isolate = heap_object->GetIsolate();
Handle<Map> map(heap_object->map(), isolate);
is_not_in_new_space_ = !isolate->heap()->InNewSpace(*object);
instance_type_ = map->instance_type();
is_undetectable_ = map->is_undetectable();
bit_field_ = IsNotInNewSpaceField::update(
bit_field_, !isolate->heap()->InNewSpace(*object));
bit_field_ = InstanceTypeField::update(bit_field_, map->instance_type());
bit_field_ =
IsUndetectableField::update(bit_field_, map->is_undetectable());
if (map->is_stable()) object_map_ = Unique<Map>::CreateImmovable(map);
has_stable_map_value_ = (instance_type_ == MAP_TYPE &&
Handle<Map>::cast(heap_object)->is_stable());
bit_field_ = HasStableMapValueField::update(
bit_field_,
HasMapValue() && Handle<Map>::cast(heap_object)->is_stable());
}
if (object->IsNumber()) {
double n = object->Number();
has_int32_value_ = IsInteger32(n);
bool has_int32_value = IsInteger32(n);
bit_field_ = HasInt32ValueField::update(bit_field_, has_int32_value);
int32_value_ = DoubleToInt32(n);
has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_);
bit_field_ = HasSmiValueField::update(
bit_field_, has_int32_value && Smi::IsValid(int32_value_));
double_value_ = n;
has_double_value_ = true;
bit_field_ = HasDoubleValueField::update(bit_field_, true);
// TODO(titzer): if this heap number is new space, tenure a new one.
}
......@@ -2711,112 +2716,104 @@ HConstant::HConstant(Handle<Object> object, Representation r)
}
HConstant::HConstant(Unique<Object> object,
Unique<Map> object_map,
bool has_stable_map_value,
Representation r,
HType type,
bool is_not_in_new_space,
bool boolean_value,
bool is_undetectable,
InstanceType instance_type)
: HTemplateInstruction<0>(type),
object_(object),
object_map_(object_map),
has_stable_map_value_(has_stable_map_value),
has_smi_value_(false),
has_int32_value_(false),
has_double_value_(false),
has_external_reference_value_(false),
is_not_in_new_space_(is_not_in_new_space),
boolean_value_(boolean_value),
is_undetectable_(is_undetectable),
instance_type_(instance_type) {
HConstant::HConstant(Unique<Object> object, Unique<Map> object_map,
bool has_stable_map_value, Representation r, HType type,
bool is_not_in_new_space, bool boolean_value,
bool is_undetectable, InstanceType instance_type)
: HTemplateInstruction<0>(type),
object_(object),
object_map_(object_map),
bit_field_(HasStableMapValueField::encode(has_stable_map_value) |
HasSmiValueField::encode(false) |
HasInt32ValueField::encode(false) |
HasDoubleValueField::encode(false) |
HasExternalReferenceValueField::encode(false) |
IsNotInNewSpaceField::encode(is_not_in_new_space) |
BooleanValueField::encode(boolean_value) |
IsUndetectableField::encode(is_undetectable) |
InstanceTypeField::encode(instance_type)) {
DCHECK(!object.handle().is_null());
DCHECK(!type.IsTaggedNumber() || type.IsNone());
Initialize(r);
}
HConstant::HConstant(int32_t integer_value,
Representation r,
bool is_not_in_new_space,
Unique<Object> object)
: object_(object),
object_map_(Handle<Map>::null()),
has_stable_map_value_(false),
has_smi_value_(Smi::IsValid(integer_value)),
has_int32_value_(true),
has_double_value_(true),
has_external_reference_value_(false),
is_not_in_new_space_(is_not_in_new_space),
boolean_value_(integer_value != 0),
is_undetectable_(false),
int32_value_(integer_value),
double_value_(FastI2D(integer_value)),
instance_type_(kUnknownInstanceType) {
HConstant::HConstant(int32_t integer_value, Representation r,
bool is_not_in_new_space, Unique<Object> object)
: object_(object),
object_map_(Handle<Map>::null()),
bit_field_(HasStableMapValueField::encode(false) |
HasSmiValueField::encode(Smi::IsValid(integer_value)) |
HasInt32ValueField::encode(true) |
HasDoubleValueField::encode(true) |
HasExternalReferenceValueField::encode(false) |
IsNotInNewSpaceField::encode(is_not_in_new_space) |
BooleanValueField::encode(integer_value != 0) |
IsUndetectableField::encode(false) |
InstanceTypeField::encode(kUnknownInstanceType)),
int32_value_(integer_value),
double_value_(FastI2D(integer_value)) {
// It's possible to create a constant with a value in Smi-range but stored
// in a (pre-existing) HeapNumber. See crbug.com/349878.
bool could_be_heapobject = r.IsTagged() && !object.handle().is_null();
bool is_smi = has_smi_value_ && !could_be_heapobject;
bool is_smi = HasSmiValue() && !could_be_heapobject;
set_type(is_smi ? HType::Smi() : HType::TaggedNumber());
Initialize(r);
}
HConstant::HConstant(double double_value,
Representation r,
bool is_not_in_new_space,
Unique<Object> object)
: object_(object),
object_map_(Handle<Map>::null()),
has_stable_map_value_(false),
has_int32_value_(IsInteger32(double_value)),
has_double_value_(true),
has_external_reference_value_(false),
is_not_in_new_space_(is_not_in_new_space),
boolean_value_(double_value != 0 && !std::isnan(double_value)),
is_undetectable_(false),
int32_value_(DoubleToInt32(double_value)),
double_value_(double_value),
instance_type_(kUnknownInstanceType) {
has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_);
HConstant::HConstant(double double_value, Representation r,
bool is_not_in_new_space, Unique<Object> object)
: object_(object),
object_map_(Handle<Map>::null()),
bit_field_(HasStableMapValueField::encode(false) |
HasInt32ValueField::encode(IsInteger32(double_value)) |
HasDoubleValueField::encode(true) |
HasExternalReferenceValueField::encode(false) |
IsNotInNewSpaceField::encode(is_not_in_new_space) |
BooleanValueField::encode(double_value != 0 &&
!std::isnan(double_value)) |
IsUndetectableField::encode(false) |
InstanceTypeField::encode(kUnknownInstanceType)),
int32_value_(DoubleToInt32(double_value)),
double_value_(double_value) {
bit_field_ = HasSmiValueField::update(
bit_field_, HasInteger32Value() && Smi::IsValid(int32_value_));
// It's possible to create a constant with a value in Smi-range but stored
// in a (pre-existing) HeapNumber. See crbug.com/349878.
bool could_be_heapobject = r.IsTagged() && !object.handle().is_null();
bool is_smi = has_smi_value_ && !could_be_heapobject;
bool is_smi = HasSmiValue() && !could_be_heapobject;
set_type(is_smi ? HType::Smi() : HType::TaggedNumber());
Initialize(r);
}
HConstant::HConstant(ExternalReference reference)
: HTemplateInstruction<0>(HType::Any()),
object_(Unique<Object>(Handle<Object>::null())),
object_map_(Handle<Map>::null()),
has_stable_map_value_(false),
has_smi_value_(false),
has_int32_value_(false),
has_double_value_(false),
has_external_reference_value_(true),
is_not_in_new_space_(true),
boolean_value_(true),
is_undetectable_(false),
external_reference_value_(reference),
instance_type_(kUnknownInstanceType) {
: HTemplateInstruction<0>(HType::Any()),
object_(Unique<Object>(Handle<Object>::null())),
object_map_(Handle<Map>::null()),
bit_field_(
HasStableMapValueField::encode(false) |
HasSmiValueField::encode(false) | HasInt32ValueField::encode(false) |
HasDoubleValueField::encode(false) |
HasExternalReferenceValueField::encode(true) |
IsNotInNewSpaceField::encode(true) | BooleanValueField::encode(true) |
IsUndetectableField::encode(false) |
InstanceTypeField::encode(kUnknownInstanceType)),
external_reference_value_(reference) {
Initialize(Representation::External());
}
void HConstant::Initialize(Representation r) {
if (r.IsNone()) {
if (has_smi_value_ && SmiValuesAre31Bits()) {
if (HasSmiValue() && SmiValuesAre31Bits()) {
r = Representation::Smi();
} else if (has_int32_value_) {
} else if (HasInteger32Value()) {
r = Representation::Integer32();
} else if (has_double_value_) {
} else if (HasDoubleValue()) {
r = Representation::Double();
} else if (has_external_reference_value_) {
} else if (HasExternalReferenceValue()) {
r = Representation::External();
} else {
Handle<Object> object = object_.handle();
......@@ -2843,16 +2840,16 @@ void HConstant::Initialize(Representation r) {
bool HConstant::ImmortalImmovable() const {
if (has_int32_value_) {
if (HasInteger32Value()) {
return false;
}
if (has_double_value_) {
if (HasDoubleValue()) {
if (IsSpecialDouble()) {
return true;
}
return false;
}
if (has_external_reference_value_) {
if (HasExternalReferenceValue()) {
return false;
}
......@@ -2893,44 +2890,35 @@ bool HConstant::EmitAtUses() {
HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
if (r.IsSmi() && !has_smi_value_) return NULL;
if (r.IsInteger32() && !has_int32_value_) return NULL;
if (r.IsDouble() && !has_double_value_) return NULL;
if (r.IsExternal() && !has_external_reference_value_) return NULL;
if (has_int32_value_) {
return new(zone) HConstant(int32_value_, r, is_not_in_new_space_, object_);
if (r.IsSmi() && !HasSmiValue()) return NULL;
if (r.IsInteger32() && !HasInteger32Value()) return NULL;
if (r.IsDouble() && !HasDoubleValue()) return NULL;
if (r.IsExternal() && !HasExternalReferenceValue()) return NULL;
if (HasInteger32Value()) {
return new (zone) HConstant(int32_value_, r, NotInNewSpace(), object_);
}
if (has_double_value_) {
return new(zone) HConstant(double_value_, r, is_not_in_new_space_, object_);
if (HasDoubleValue()) {
return new (zone) HConstant(double_value_, r, NotInNewSpace(), object_);
}
if (has_external_reference_value_) {
if (HasExternalReferenceValue()) {
return new(zone) HConstant(external_reference_value_);
}
DCHECK(!object_.handle().is_null());
return new(zone) HConstant(object_,
object_map_,
has_stable_map_value_,
r,
type_,
is_not_in_new_space_,
boolean_value_,
is_undetectable_,
instance_type_);
return new (zone) HConstant(object_, object_map_, HasStableMapValue(), r,
type_, NotInNewSpace(), BooleanValue(),
IsUndetectable(), GetInstanceType());
}
Maybe<HConstant*> HConstant::CopyToTruncatedInt32(Zone* zone) {
HConstant* res = NULL;
if (has_int32_value_) {
res = new(zone) HConstant(int32_value_,
Representation::Integer32(),
is_not_in_new_space_,
object_);
} else if (has_double_value_) {
res = new(zone) HConstant(DoubleToInt32(double_value_),
Representation::Integer32(),
is_not_in_new_space_,
object_);
if (HasInteger32Value()) {
res = new (zone) HConstant(int32_value_, Representation::Integer32(),
NotInNewSpace(), object_);
} else if (HasDoubleValue()) {
res = new (zone)
HConstant(DoubleToInt32(double_value_), Representation::Integer32(),
NotInNewSpace(), object_);
}
return Maybe<HConstant*>(res != NULL, res);
}
......@@ -2952,11 +2940,11 @@ Maybe<HConstant*> HConstant::CopyToTruncatedNumber(Zone* zone) {
std::ostream& HConstant::PrintDataTo(std::ostream& os) const { // NOLINT
if (has_int32_value_) {
if (HasInteger32Value()) {
os << int32_value_ << " ";
} else if (has_double_value_) {
} else if (HasDoubleValue()) {
os << double_value_ << " ";
} else if (has_external_reference_value_) {
} else if (HasExternalReferenceValue()) {
os << reinterpret_cast<void*>(external_reference_value_.address()) << " ";
} else {
// The handle() method is silently and lazily mutating the object.
......@@ -2965,7 +2953,7 @@ std::ostream& HConstant::PrintDataTo(std::ostream& os) const { // NOLINT
if (HasStableMapValue()) os << "[stable-map] ";
if (HasObjectMap()) os << "[map " << *ObjectMap().handle() << "] ";
}
if (!is_not_in_new_space_) os << "[new space] ";
if (!NotInNewSpace()) os << "[new space] ";
return os;
}
......
......@@ -1497,13 +1497,18 @@ class HCompareMap FINAL : public HUnaryControlInstruction {
virtual std::ostream& PrintDataTo(std::ostream& os) const OVERRIDE; // NOLINT
static const int kNoKnownSuccessorIndex = -1;
int known_successor_index() const { return known_successor_index_; }
void set_known_successor_index(int known_successor_index) {
known_successor_index_ = known_successor_index;
int known_successor_index() const {
return KnownSuccessorIndexField::decode(bit_field_) -
kInternalKnownSuccessorOffset;
}
void set_known_successor_index(int index) {
DCHECK(index >= 0 - kInternalKnownSuccessorOffset);
bit_field_ = KnownSuccessorIndexField::update(
bit_field_, index + kInternalKnownSuccessorOffset);
}
Unique<Map> map() const { return map_; }
bool map_is_stable() const { return map_is_stable_; }
bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
return Representation::Tagged();
......@@ -1515,19 +1520,25 @@ class HCompareMap FINAL : public HUnaryControlInstruction {
virtual int RedefinedOperandIndex() OVERRIDE { return 0; }
private:
HCompareMap(HValue* value,
Handle<Map> map,
HBasicBlock* true_target = NULL,
HCompareMap(HValue* value, Handle<Map> map, HBasicBlock* true_target = NULL,
HBasicBlock* false_target = NULL)
: HUnaryControlInstruction(value, true_target, false_target),
known_successor_index_(kNoKnownSuccessorIndex),
map_is_stable_(map->is_stable()),
bit_field_(KnownSuccessorIndexField::encode(
kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset) |
MapIsStableField::encode(map->is_stable())),
map_(Unique<Map>::CreateImmovable(map)) {
set_representation(Representation::Tagged());
}
int known_successor_index_ : 31;
bool map_is_stable_ : 1;
// BitFields can only store unsigned values, so use an offset.
// Adding kInternalKnownSuccessorOffset must yield an unsigned value.
static const int kInternalKnownSuccessorOffset = 1;
STATIC_ASSERT(kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset >= 0);
class KnownSuccessorIndexField : public BitField<int, 0, 31> {};
class MapIsStableField : public BitField<bool, 31, 1> {};
uint32_t bit_field_;
Unique<Map> map_;
};
......@@ -1803,17 +1814,15 @@ enum RemovableSimulate {
class HSimulate FINAL : public HInstruction {
public:
HSimulate(BailoutId ast_id,
int pop_count,
Zone* zone,
HSimulate(BailoutId ast_id, int pop_count, Zone* zone,
RemovableSimulate removable)
: ast_id_(ast_id),
pop_count_(pop_count),
values_(2, zone),
assigned_indexes_(2, zone),
zone_(zone),
removable_(removable),
done_with_replay_(false) {}
bit_field_(RemovableField::encode(removable) |
DoneWithReplayField::encode(false)) {}
~HSimulate() {}
virtual std::ostream& PrintDataTo(std::ostream& os) const OVERRIDE; // NOLINT
......@@ -1857,7 +1866,9 @@ class HSimulate FINAL : public HInstruction {
}
void MergeWith(ZoneList<HSimulate*>* list);
bool is_candidate_for_removal() { return removable_ == REMOVABLE_SIMULATE; }
bool is_candidate_for_removal() {
return RemovableField::decode(bit_field_) == REMOVABLE_SIMULATE;
}
// Replay effects of this instruction on the given environment.
void ReplayEnvironment(HEnvironment* env);
......@@ -1891,13 +1902,22 @@ class HSimulate FINAL : public HInstruction {
}
return false;
}
bool is_done_with_replay() const {
return DoneWithReplayField::decode(bit_field_);
}
void set_done_with_replay() {
bit_field_ = DoneWithReplayField::update(bit_field_, true);
}
class RemovableField : public BitField<RemovableSimulate, 0, 1> {};
class DoneWithReplayField : public BitField<bool, 1, 1> {};
BailoutId ast_id_;
int pop_count_;
ZoneList<HValue*> values_;
ZoneList<int> assigned_indexes_;
Zone* zone_;
RemovableSimulate removable_ : 2;
bool done_with_replay_ : 1;
uint32_t bit_field_;
#ifdef DEBUG
Handle<JSFunction> closure_;
......@@ -2742,11 +2762,13 @@ class HCheckMaps FINAL : public HTemplateInstruction<2> {
return new(zone) HCheckMaps(value, maps, typecheck);
}
bool IsStabilityCheck() const { return is_stability_check_; }
bool IsStabilityCheck() const {
return IsStabilityCheckField::decode(bit_field_);
}
void MarkAsStabilityCheck() {
maps_are_stable_ = true;
has_migration_target_ = false;
is_stability_check_ = true;
bit_field_ = MapsAreStableField::encode(true) |
HasMigrationTargetField::encode(false) |
IsStabilityCheckField::encode(true);
ClearChangesFlag(kNewSpacePromotion);
ClearDependsOnFlag(kElementsKind);
ClearDependsOnFlag(kMaps);
......@@ -2770,9 +2792,13 @@ class HCheckMaps FINAL : public HTemplateInstruction<2> {
const UniqueSet<Map>* maps() const { return maps_; }
void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
bool maps_are_stable() const { return maps_are_stable_; }
bool maps_are_stable() const {
return MapsAreStableField::decode(bit_field_);
}
bool HasMigrationTarget() const { return has_migration_target_; }
bool HasMigrationTarget() const {
return HasMigrationTargetField::decode(bit_field_);
}
virtual HValue* Canonicalize() OVERRIDE;
......@@ -2804,9 +2830,11 @@ class HCheckMaps FINAL : public HTemplateInstruction<2> {
private:
HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
: HTemplateInstruction<2>(HType::HeapObject()), maps_(maps),
has_migration_target_(false), is_stability_check_(false),
maps_are_stable_(maps_are_stable) {
: HTemplateInstruction<2>(HType::HeapObject()),
maps_(maps),
bit_field_(HasMigrationTargetField::encode(false) |
IsStabilityCheckField::encode(false) |
MapsAreStableField::encode(maps_are_stable)) {
DCHECK_NE(0, maps->size());
SetOperandAt(0, value);
// Use the object value for the dependency.
......@@ -2818,9 +2846,11 @@ class HCheckMaps FINAL : public HTemplateInstruction<2> {
}
HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
: HTemplateInstruction<2>(HType::HeapObject()), maps_(maps),
has_migration_target_(false), is_stability_check_(false),
maps_are_stable_(true) {
: HTemplateInstruction<2>(HType::HeapObject()),
maps_(maps),
bit_field_(HasMigrationTargetField::encode(false) |
IsStabilityCheckField::encode(false) |
MapsAreStableField::encode(true)) {
DCHECK_NE(0, maps->size());
SetOperandAt(0, value);
// Use the object value for the dependency if NULL is passed.
......@@ -2831,16 +2861,22 @@ class HCheckMaps FINAL : public HTemplateInstruction<2> {
SetDependsOnFlag(kElementsKind);
for (int i = 0; i < maps->size(); ++i) {
Handle<Map> map = maps->at(i).handle();
if (map->is_migration_target()) has_migration_target_ = true;
if (!map->is_stable()) maps_are_stable_ = false;
if (map->is_migration_target()) {
bit_field_ = HasMigrationTargetField::update(bit_field_, true);
}
if (!map->is_stable()) {
bit_field_ = MapsAreStableField::update(bit_field_, false);
}
}
if (has_migration_target_) SetChangesFlag(kNewSpacePromotion);
if (HasMigrationTarget()) SetChangesFlag(kNewSpacePromotion);
}
class HasMigrationTargetField : public BitField<bool, 0, 1> {};
class IsStabilityCheckField : public BitField<bool, 1, 1> {};
class MapsAreStableField : public BitField<bool, 2, 1> {};
const UniqueSet<Map>* maps_;
bool has_migration_target_ : 1;
bool is_stability_check_ : 1;
bool maps_are_stable_ : 1;
uint32_t bit_field_;
};
......@@ -3537,29 +3573,26 @@ class HConstant FINAL : public HTemplateInstruction<0> {
isolate->factory()->NewNumber(double_value_, TENURED));
}
AllowDeferredHandleDereference smi_check;
DCHECK(has_int32_value_ || !object_.handle()->IsSmi());
DCHECK(HasInteger32Value() || !object_.handle()->IsSmi());
return object_.handle();
}
bool IsSpecialDouble() const {
return has_double_value_ &&
return HasDoubleValue() &&
(bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
FixedDoubleArray::is_the_hole_nan(double_value_) ||
std::isnan(double_value_));
}
bool NotInNewSpace() const {
return is_not_in_new_space_;
return IsNotInNewSpaceField::decode(bit_field_);
}
bool ImmortalImmovable() const;
bool IsCell() const {
return instance_type_ == CELL_TYPE || instance_type_ == PROPERTY_CELL_TYPE;
}
bool IsMap() const {
return instance_type_ == MAP_TYPE;
InstanceType instance_type = GetInstanceType();
return instance_type == CELL_TYPE || instance_type == PROPERTY_CELL_TYPE;
}
virtual Representation RequiredInputRepresentation(int index) OVERRIDE {
......@@ -3579,13 +3612,17 @@ class HConstant FINAL : public HTemplateInstruction<0> {
HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
Maybe<HConstant*> CopyToTruncatedNumber(Zone* zone);
bool HasInteger32Value() const { return has_int32_value_; }
bool HasInteger32Value() const {
return HasInt32ValueField::decode(bit_field_);
}
int32_t Integer32Value() const {
DCHECK(HasInteger32Value());
return int32_value_;
}
bool HasSmiValue() const { return has_smi_value_; }
bool HasDoubleValue() const { return has_double_value_; }
bool HasSmiValue() const { return HasSmiValueField::decode(bit_field_); }
bool HasDoubleValue() const {
return HasDoubleValueField::decode(bit_field_);
}
double DoubleValue() const {
DCHECK(HasDoubleValue());
return double_value_;
......@@ -3597,7 +3634,7 @@ class HConstant FINAL : public HTemplateInstruction<0> {
return object_.IsInitialized() &&
object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
}
bool HasNumberValue() const { return has_double_value_; }
bool HasNumberValue() const { return HasDoubleValue(); }
int32_t NumberValueAsInteger32() const {
DCHECK(HasNumberValue());
// Irrespective of whether a numeric HConstant can be safely
......@@ -3606,38 +3643,42 @@ class HConstant FINAL : public HTemplateInstruction<0> {
return int32_value_;
}
bool HasStringValue() const {
if (has_double_value_ || has_int32_value_) return false;
if (HasNumberValue()) return false;
DCHECK(!object_.handle().is_null());
return instance_type_ < FIRST_NONSTRING_TYPE;
return GetInstanceType() < FIRST_NONSTRING_TYPE;
}
Handle<String> StringValue() const {
DCHECK(HasStringValue());
return Handle<String>::cast(object_.handle());
}
bool HasInternalizedStringValue() const {
return HasStringValue() && StringShape(instance_type_).IsInternalized();
return HasStringValue() && StringShape(GetInstanceType()).IsInternalized();
}
bool HasExternalReferenceValue() const {
return has_external_reference_value_;
return HasExternalReferenceValueField::decode(bit_field_);
}
ExternalReference ExternalReferenceValue() const {
return external_reference_value_;
}
bool HasBooleanValue() const { return type_.IsBoolean(); }
bool BooleanValue() const { return boolean_value_; }
bool IsUndetectable() const { return is_undetectable_; }
InstanceType GetInstanceType() const { return instance_type_; }
bool BooleanValue() const { return BooleanValueField::decode(bit_field_); }
bool IsUndetectable() const {
return IsUndetectableField::decode(bit_field_);
}
InstanceType GetInstanceType() const {
return InstanceTypeField::decode(bit_field_);
}
bool HasMapValue() const { return instance_type_ == MAP_TYPE; }
bool HasMapValue() const { return GetInstanceType() == MAP_TYPE; }
Unique<Map> MapValue() const {
DCHECK(HasMapValue());
return Unique<Map>::cast(GetUnique());
}
bool HasStableMapValue() const {
DCHECK(HasMapValue() || !has_stable_map_value_);
return has_stable_map_value_;
DCHECK(HasMapValue() || !HasStableMapValueField::decode(bit_field_));
return HasStableMapValueField::decode(bit_field_);
}
bool HasObjectMap() const { return !object_map_.IsNull(); }
......@@ -3647,11 +3688,11 @@ class HConstant FINAL : public HTemplateInstruction<0> {
}
virtual intptr_t Hashcode() OVERRIDE {
if (has_int32_value_) {
if (HasInteger32Value()) {
return static_cast<intptr_t>(int32_value_);
} else if (has_double_value_) {
} else if (HasDoubleValue()) {
return static_cast<intptr_t>(bit_cast<int64_t>(double_value_));
} else if (has_external_reference_value_) {
} else if (HasExternalReferenceValue()) {
return reinterpret_cast<intptr_t>(external_reference_value_.address());
} else {
DCHECK(!object_.handle().is_null());
......@@ -3660,7 +3701,7 @@ class HConstant FINAL : public HTemplateInstruction<0> {
}
virtual void FinalizeUniqueness() OVERRIDE {
if (!has_double_value_ && !has_external_reference_value_) {
if (!HasDoubleValue() && !HasExternalReferenceValue()) {
DCHECK(!object_.handle().is_null());
object_ = Unique<Object>(object_.handle());
}
......@@ -3676,21 +3717,21 @@ class HConstant FINAL : public HTemplateInstruction<0> {
virtual bool DataEquals(HValue* other) OVERRIDE {
HConstant* other_constant = HConstant::cast(other);
if (has_int32_value_) {
return other_constant->has_int32_value_ &&
int32_value_ == other_constant->int32_value_;
} else if (has_double_value_) {
return other_constant->has_double_value_ &&
if (HasInteger32Value()) {
return other_constant->HasInteger32Value() &&
int32_value_ == other_constant->int32_value_;
} else if (HasDoubleValue()) {
return other_constant->HasDoubleValue() &&
bit_cast<int64_t>(double_value_) ==
bit_cast<int64_t>(other_constant->double_value_);
} else if (has_external_reference_value_) {
return other_constant->has_external_reference_value_ &&
external_reference_value_ ==
other_constant->external_reference_value_;
} else if (HasExternalReferenceValue()) {
return other_constant->HasExternalReferenceValue() &&
external_reference_value_ ==
other_constant->external_reference_value_;
} else {
if (other_constant->has_int32_value_ ||
other_constant->has_double_value_ ||
other_constant->has_external_reference_value_) {
if (other_constant->HasInteger32Value() ||
other_constant->HasDoubleValue() ||
other_constant->HasExternalReferenceValue()) {
return false;
}
DCHECK(!object_.handle().is_null());
......@@ -3735,6 +3776,25 @@ class HConstant FINAL : public HTemplateInstruction<0> {
virtual bool IsDeletable() const OVERRIDE { return true; }
// If object_ is a map, this indicates whether the map is stable.
class HasStableMapValueField : public BitField<bool, 0, 1> {};
// We store the HConstant in the most specific form safely possible.
// These flags tell us if the respective member fields hold valid, safe
// representations of the constant. More specific flags imply more general
// flags, but not the converse (i.e. smi => int32 => double).
class HasSmiValueField : public BitField<bool, 1, 1> {};
class HasInt32ValueField : public BitField<bool, 2, 1> {};
class HasDoubleValueField : public BitField<bool, 3, 1> {};
class HasExternalReferenceValueField : public BitField<bool, 4, 1> {};
class IsNotInNewSpaceField : public BitField<bool, 5, 1> {};
class BooleanValueField : public BitField<bool, 6, 1> {};
class IsUndetectableField : public BitField<bool, 7, 1> {};
static const InstanceType kUnknownInstanceType = FILLER_TYPE;
class InstanceTypeField : public BitField<InstanceType, 8, 8> {};
// If this is a numerical constant, object_ either points to the
// HeapObject the constant originated from or is null. If the
// constant is non-numeric, object_ always points to a valid
......@@ -3744,27 +3804,11 @@ class HConstant FINAL : public HTemplateInstruction<0> {
// If object_ is a heap object, this points to the stable map of the object.
Unique<Map> object_map_;
// If object_ is a map, this indicates whether the map is stable.
bool has_stable_map_value_ : 1;
uint32_t bit_field_;
// We store the HConstant in the most specific form safely possible.
// The two flags, has_int32_value_ and has_double_value_ tell us if
// int32_value_ and double_value_ hold valid, safe representations
// of the constant. has_int32_value_ implies has_double_value_ but
// not the converse.
bool has_smi_value_ : 1;
bool has_int32_value_ : 1;
bool has_double_value_ : 1;
bool has_external_reference_value_ : 1;
bool is_not_in_new_space_ : 1;
bool boolean_value_ : 1;
bool is_undetectable_: 1;
int32_t int32_value_;
double double_value_;
ExternalReference external_reference_value_;
static const InstanceType kUnknownInstanceType = FILLER_TYPE;
InstanceType instance_type_;
};
......@@ -6739,8 +6783,8 @@ class HLoadKeyed FINAL
kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
};
STATIC_ASSERT((kBitsForElementsKind + kBitsForBaseOffset +
kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
STATIC_ASSERT((kBitsForElementsKind + kBitsForHoleMode + kBitsForBaseOffset +
kBitsForIsDehoisted) <= sizeof(uint32_t) * 8);
STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
class ElementsKindField:
public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
......@@ -6845,7 +6889,8 @@ class HStoreNamedField FINAL : public HTemplateInstruction<3> {
} else if (field_representation().IsDouble()) {
return field_representation();
} else if (field_representation().IsSmi()) {
if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
if (SmiValuesAre32Bits() &&
store_mode() == STORE_TO_INITIALIZED_ENTRY) {
return Representation::Integer32();
}
return field_representation();
......@@ -6870,8 +6915,10 @@ class HStoreNamedField FINAL : public HTemplateInstruction<3> {
HObjectAccess access() const { return access_; }
HValue* dominator() const { return dominator_; }
bool has_transition() const { return has_transition_; }
StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
bool has_transition() const { return HasTransitionField::decode(bit_field_); }
StoreFieldOrKeyedMode store_mode() const {
return StoreModeField::decode(bit_field_);
}
Handle<Map> transition_map() const {
if (has_transition()) {
......@@ -6885,7 +6932,7 @@ class HStoreNamedField FINAL : public HTemplateInstruction<3> {
void SetTransition(HConstant* transition) {
DCHECK(!has_transition()); // Only set once.
SetOperandAt(2, transition);
has_transition_ = true;
bit_field_ = HasTransitionField::update(bit_field_, true);
SetChangesFlag(kMaps);
}
......@@ -6936,14 +6983,12 @@ class HStoreNamedField FINAL : public HTemplateInstruction<3> {
}
private:
HStoreNamedField(HValue* obj,
HObjectAccess access,
HValue* val,
HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val,
StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
: access_(access),
dominator_(NULL),
has_transition_(false),
store_mode_(store_mode) {
bit_field_(HasTransitionField::encode(false) |
StoreModeField::encode(store_mode)) {
// Stores to a non existing in-object property are allowed only to the
// newly allocated objects (via HAllocate or HInnerAllocatedObject).
DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
......@@ -6954,10 +6999,12 @@ class HStoreNamedField FINAL : public HTemplateInstruction<3> {
access.SetGVNFlags(this, STORE);
}
class HasTransitionField : public BitField<bool, 0, 1> {};
class StoreModeField : public BitField<StoreFieldOrKeyedMode, 1, 1> {};
HObjectAccess access_;
HValue* dominator_;
bool has_transition_ : 1;
StoreFieldOrKeyedMode store_mode_ : 1;
uint32_t bit_field_;
};
......@@ -7024,7 +7071,7 @@ class HStoreKeyed FINAL
}
DCHECK_EQ(index, 2);
return RequiredValueRepresentation(elements_kind_, store_mode_);
return RequiredValueRepresentation(elements_kind(), store_mode());
}
static Representation RequiredValueRepresentation(
......@@ -7065,7 +7112,8 @@ class HStoreKeyed FINAL
if (IsUninitialized()) {
return Representation::None();
}
Representation r = RequiredValueRepresentation(elements_kind_, store_mode_);
Representation r =
RequiredValueRepresentation(elements_kind(), store_mode());
// For fast object elements kinds, don't assume anything.
if (r.IsTagged()) return Representation::None();
return r;
......@@ -7074,22 +7122,26 @@ class HStoreKeyed FINAL
HValue* elements() const { return OperandAt(0); }
HValue* key() const { return OperandAt(1); }
HValue* value() const { return OperandAt(2); }
bool value_is_smi() const {
return IsFastSmiElementsKind(elements_kind_);
bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
StoreFieldOrKeyedMode store_mode() const {
return StoreModeField::decode(bit_field_);
}
ElementsKind elements_kind() const OVERRIDE {
return ElementsKindField::decode(bit_field_);
}
StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
ElementsKind elements_kind() const OVERRIDE { return elements_kind_; }
uint32_t base_offset() const { return base_offset_; }
bool TryIncreaseBaseOffset(uint32_t increase_by_value) OVERRIDE;
HValue* GetKey() OVERRIDE { return key(); }
void SetKey(HValue* key) OVERRIDE { SetOperandAt(1, key); }
bool IsDehoisted() const OVERRIDE { return is_dehoisted_; }
bool IsDehoisted() const OVERRIDE {
return IsDehoistedField::decode(bit_field_);
}
void SetDehoisted(bool is_dehoisted) OVERRIDE {
is_dehoisted_ = is_dehoisted;
bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
}
bool IsUninitialized() { return is_uninitialized_; }
bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
void SetUninitialized(bool is_uninitialized) {
is_uninitialized_ = is_uninitialized;
bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
}
bool IsConstantHoleStore() {
......@@ -7125,18 +7177,17 @@ class HStoreKeyed FINAL
DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
private:
HStoreKeyed(HValue* obj, HValue* key, HValue* val,
ElementsKind elements_kind,
HStoreKeyed(HValue* obj, HValue* key, HValue* val, ElementsKind elements_kind,
StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
int offset = kDefaultKeyedHeaderOffsetSentinel)
: elements_kind_(elements_kind),
base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
? GetDefaultHeaderSizeForElementsKind(elements_kind)
: offset),
is_dehoisted_(false),
is_uninitialized_(false),
store_mode_(store_mode),
dominator_(NULL) {
: base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
? GetDefaultHeaderSizeForElementsKind(elements_kind)
: offset),
bit_field_(IsDehoistedField::encode(false) |
IsUninitializedField::encode(false) |
StoreModeField::encode(store_mode) |
ElementsKindField::encode(elements_kind)),
dominator_(NULL) {
SetOperandAt(0, obj);
SetOperandAt(1, key);
SetOperandAt(2, val);
......@@ -7168,11 +7219,13 @@ class HStoreKeyed FINAL
}
}
ElementsKind elements_kind_;
class IsDehoistedField : public BitField<bool, 0, 1> {};
class IsUninitializedField : public BitField<bool, 1, 1> {};
class StoreModeField : public BitField<StoreFieldOrKeyedMode, 2, 1> {};
class ElementsKindField : public BitField<ElementsKind, 3, 5> {};
uint32_t base_offset_;
bool is_dehoisted_ : 1;
bool is_uninitialized_ : 1;
StoreFieldOrKeyedMode store_mode_: 1;
uint32_t bit_field_;
HValue* dominator_;
};
......@@ -7496,23 +7549,25 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
bool pretenure() const { return pretenure_; }
bool has_no_literals() const { return has_no_literals_; }
bool is_arrow() const { return IsArrowFunction(kind_); }
bool is_generator() const { return IsGeneratorFunction(kind_); }
bool is_concise_method() const { return IsConciseMethod(kind_); }
FunctionKind kind() const { return kind_; }
StrictMode strict_mode() const { return strict_mode_; }
bool pretenure() const { return PretenureField::decode(bit_field_); }
bool has_no_literals() const {
return HasNoLiteralsField::decode(bit_field_);
}
bool is_arrow() const { return IsArrowFunction(kind()); }
bool is_generator() const { return IsGeneratorFunction(kind()); }
bool is_concise_method() const { return IsConciseMethod(kind()); }
FunctionKind kind() const { return FunctionKindField::decode(bit_field_); }
StrictMode strict_mode() const { return StrictModeField::decode(bit_field_); }
private:
HFunctionLiteral(HValue* context, Handle<SharedFunctionInfo> shared,
bool pretenure)
: HTemplateInstruction<1>(HType::JSObject()),
shared_info_(shared),
kind_(shared->kind()),
pretenure_(pretenure),
has_no_literals_(shared->num_literals() == 0),
strict_mode_(shared->strict_mode()) {
bit_field_(FunctionKindField::encode(shared->kind()) |
PretenureField::encode(pretenure) |
HasNoLiteralsField::encode(shared->num_literals() == 0) |
StrictModeField::encode(shared->strict_mode())) {
SetOperandAt(0, context);
set_representation(Representation::Tagged());
SetChangesFlag(kNewSpacePromotion);
......@@ -7520,11 +7575,13 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
virtual bool IsDeletable() const OVERRIDE { return true; }
class FunctionKindField : public BitField<FunctionKind, 0, 3> {};
class PretenureField : public BitField<bool, 3, 1> {};
class HasNoLiteralsField : public BitField<bool, 4, 1> {};
class StrictModeField : public BitField<StrictMode, 5, 1> {};
Handle<SharedFunctionInfo> shared_info_;
FunctionKind kind_;
bool pretenure_ : 1;
bool has_no_literals_ : 1;
StrictMode strict_mode_;
uint32_t bit_field_;
};
......
......@@ -10,14 +10,11 @@
namespace v8 {
namespace internal {
CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
const char* name,
const char* name_prefix,
const char* resource_name,
int line_number,
int column_number)
: tag_(tag),
builtin_id_(Builtins::builtin_count),
CodeEntry::CodeEntry(Logger::LogEventsAndTags tag, const char* name,
const char* name_prefix, const char* resource_name,
int line_number, int column_number)
: bit_field_(TagField::encode(tag) |
BuiltinIdField::encode(Builtins::builtin_count)),
name_prefix_(name_prefix),
name_(name),
resource_name_(resource_name),
......@@ -26,7 +23,7 @@ CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
shared_id_(0),
script_id_(v8::UnboundScript::kNoScriptId),
no_frame_ranges_(NULL),
bailout_reason_(kEmptyBailoutReason) { }
bailout_reason_(kEmptyBailoutReason) {}
bool CodeEntry::is_js_function_tag(Logger::LogEventsAndTags tag) {
......
......@@ -143,7 +143,7 @@ CodeEntry::~CodeEntry() {
uint32_t CodeEntry::GetCallUid() const {
uint32_t hash = ComputeIntegerHash(tag_, v8::internal::kZeroHashSeed);
uint32_t hash = ComputeIntegerHash(tag(), v8::internal::kZeroHashSeed);
if (shared_id_ != 0) {
hash ^= ComputeIntegerHash(static_cast<uint32_t>(shared_id_),
v8::internal::kZeroHashSeed);
......@@ -164,20 +164,18 @@ uint32_t CodeEntry::GetCallUid() const {
bool CodeEntry::IsSameAs(CodeEntry* entry) const {
return this == entry
|| (tag_ == entry->tag_
&& shared_id_ == entry->shared_id_
&& (shared_id_ != 0
|| (name_prefix_ == entry->name_prefix_
&& name_ == entry->name_
&& resource_name_ == entry->resource_name_
&& line_number_ == entry->line_number_)));
return this == entry ||
(tag() == entry->tag() && shared_id_ == entry->shared_id_ &&
(shared_id_ != 0 ||
(name_prefix_ == entry->name_prefix_ && name_ == entry->name_ &&
resource_name_ == entry->resource_name_ &&
line_number_ == entry->line_number_)));
}
void CodeEntry::SetBuiltinId(Builtins::Name id) {
tag_ = Logger::BUILTIN_TAG;
builtin_id_ = id;
bit_field_ = TagField::update(bit_field_, Logger::BUILTIN_TAG);
bit_field_ = BuiltinIdField::update(bit_field_, id);
}
......
......@@ -55,7 +55,7 @@ class CodeEntry {
int column_number = v8::CpuProfileNode::kNoColumnNumberInfo);
~CodeEntry();
bool is_js_function() const { return is_js_function_tag(tag_); }
bool is_js_function() const { return is_js_function_tag(tag()); }
const char* name_prefix() const { return name_prefix_; }
bool has_name_prefix() const { return name_prefix_[0] != '\0'; }
const char* name() const { return name_; }
......@@ -78,7 +78,9 @@ class CodeEntry {
}
void SetBuiltinId(Builtins::Name id);
Builtins::Name builtin_id() const { return builtin_id_; }
Builtins::Name builtin_id() const {
return BuiltinIdField::decode(bit_field_);
}
uint32_t GetCallUid() const;
bool IsSameAs(CodeEntry* entry) const;
......@@ -88,8 +90,11 @@ class CodeEntry {
static const char* const kEmptyBailoutReason;
private:
Logger::LogEventsAndTags tag_ : 8;
Builtins::Name builtin_id_ : 8;
class TagField : public BitField<Logger::LogEventsAndTags, 0, 8> {};
class BuiltinIdField : public BitField<Builtins::Name, 8, 8> {};
Logger::LogEventsAndTags tag() const { return TagField::decode(bit_field_); }
uint32_t bit_field_;
const char* name_prefix_;
const char* name_;
const char* resource_name_;
......
......@@ -104,19 +104,19 @@ class ArrayConcatVisitor {
storage_(Handle<FixedArray>::cast(
isolate->global_handles()->Create(*storage))),
index_offset_(0u),
fast_elements_(fast_elements),
exceeds_array_limit_(false) {}
bit_field_(FastElementsField::encode(fast_elements) |
ExceedsLimitField::encode(false)) {}
~ArrayConcatVisitor() { clear_storage(); }
void visit(uint32_t i, Handle<Object> elm) {
if (i > JSObject::kMaxElementCount - index_offset_) {
exceeds_array_limit_ = true;
set_exceeds_array_limit(true);
return;
}
uint32_t index = index_offset_ + i;
if (fast_elements_) {
if (fast_elements()) {
if (index < static_cast<uint32_t>(storage_->length())) {
storage_->set(index, *elm);
return;
......@@ -128,7 +128,7 @@ class ArrayConcatVisitor {
SetDictionaryMode();
// Fall-through to dictionary mode.
}
DCHECK(!fast_elements_);
DCHECK(!fast_elements());
Handle<SeededNumberDictionary> dict(
SeededNumberDictionary::cast(*storage_));
Handle<SeededNumberDictionary> result =
......@@ -149,21 +149,23 @@ class ArrayConcatVisitor {
// If the initial length estimate was off (see special case in visit()),
// but the array blowing the limit didn't contain elements beyond the
// provided-for index range, go to dictionary mode now.
if (fast_elements_ &&
if (fast_elements() &&
index_offset_ >
static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
SetDictionaryMode();
}
}
bool exceeds_array_limit() { return exceeds_array_limit_; }
bool exceeds_array_limit() const {
return ExceedsLimitField::decode(bit_field_);
}
Handle<JSArray> ToArray() {
Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
Handle<Object> length =
isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
Handle<Map> map = JSObject::GetElementsTransitionMap(
array, fast_elements_ ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
array->set_map(*map);
array->set_length(*length);
array->set_elements(*storage_);
......@@ -173,7 +175,7 @@ class ArrayConcatVisitor {
private:
// Convert storage to dictionary mode.
void SetDictionaryMode() {
DCHECK(fast_elements_);
DCHECK(fast_elements());
Handle<FixedArray> current_storage(*storage_);
Handle<SeededNumberDictionary> slow_storage(
SeededNumberDictionary::New(isolate_, current_storage->length()));
......@@ -191,7 +193,7 @@ class ArrayConcatVisitor {
}
clear_storage();
set_storage(*slow_storage);
fast_elements_ = false;
set_fast_elements(false);
}
inline void clear_storage() {
......@@ -203,13 +205,23 @@ class ArrayConcatVisitor {
Handle<FixedArray>::cast(isolate_->global_handles()->Create(storage));
}
class FastElementsField : public BitField<bool, 0, 1> {};
class ExceedsLimitField : public BitField<bool, 1, 1> {};
bool fast_elements() const { return FastElementsField::decode(bit_field_); }
void set_fast_elements(bool fast) {
bit_field_ = FastElementsField::update(bit_field_, fast);
}
void set_exceeds_array_limit(bool exceeds) {
bit_field_ = ExceedsLimitField::update(bit_field_, exceeds);
}
Isolate* isolate_;
Handle<FixedArray> storage_; // Always a global handle.
// Index after last seen index. Always less than or equal to
// JSObject::kMaxElementCount.
uint32_t index_offset_;
bool fast_elements_ : 1;
bool exceeds_array_limit_ : 1;
uint32_t bit_field_;
};
......
......@@ -245,6 +245,8 @@ bool Scanner::SkipWhiteSpace() {
while (true) {
while (true) {
// The unicode cache accepts unsigned inputs.
if (c0_ < 0) break;
// Advance as long as character is a WhiteSpace or LineTerminator.
// Remember if the latter is the case.
if (unicode_cache_->IsLineTerminator(c0_)) {
......@@ -365,7 +367,7 @@ Token::Value Scanner::SkipMultiLineComment() {
while (c0_ >= 0) {
uc32 ch = c0_;
Advance();
if (unicode_cache_->IsLineTerminator(ch)) {
if (c0_ >= 0 && unicode_cache_->IsLineTerminator(ch)) {
// Following ECMA-262, section 7.4, a comment containing
// a newline will make the comment count as a line-terminator.
has_multiline_comment_before_next_ = true;
......@@ -625,14 +627,14 @@ void Scanner::Scan() {
break;
default:
if (unicode_cache_->IsIdentifierStart(c0_)) {
if (c0_ < 0) {
token = Token::EOS;
} else if (unicode_cache_->IsIdentifierStart(c0_)) {
token = ScanIdentifierOrKeyword();
} else if (IsDecimalDigit(c0_)) {
token = ScanNumber(false);
} else if (SkipWhiteSpace()) {
token = Token::WHITESPACE;
} else if (c0_ < 0) {
token = Token::EOS;
} else {
token = Select(Token::ILLEGAL);
}
......@@ -674,7 +676,7 @@ bool Scanner::ScanEscape() {
Advance();
// Skip escaped newlines.
if (unicode_cache_->IsLineTerminator(c)) {
if (c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) {
// Allow CR+LF newlines in multiline string literals.
if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
// Allow LF+CR newlines in multiline string literals.
......@@ -871,7 +873,8 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
// not be an identifier start or a decimal digit; see ECMA-262
// section 7.8.3, page 17 (note that we read only one decimal digit
// if the value is 0).
if (IsDecimalDigit(c0_) || unicode_cache_->IsIdentifierStart(c0_))
if (IsDecimalDigit(c0_) ||
(c0_ >= 0 && unicode_cache_->IsIdentifierStart(c0_)))
return Token::ILLEGAL;
literal.Complete();
......@@ -1039,7 +1042,7 @@ Token::Value Scanner::ScanIdentifierOrKeyword() {
AddLiteralChar(first_char);
// Scan the rest of the identifier characters.
while (unicode_cache_->IsIdentifierPart(c0_)) {
while (c0_ >= 0 && unicode_cache_->IsIdentifierPart(c0_)) {
if (c0_ != '\\') {
uc32 next_char = c0_;
Advance();
......@@ -1067,7 +1070,7 @@ Token::Value Scanner::ScanIdentifierOrKeyword() {
Token::Value Scanner::ScanIdentifierSuffix(LiteralScope* literal) {
// Scan the rest of the identifier characters.
while (unicode_cache_->IsIdentifierPart(c0_)) {
while (c0_ >= 0 && unicode_cache_->IsIdentifierPart(c0_)) {
if (c0_ == '\\') {
uc32 c = ScanIdentifierUnicodeEscape();
// Only allow legal identifier part characters.
......@@ -1106,10 +1109,10 @@ bool Scanner::ScanRegExpPattern(bool seen_equal) {
}
while (c0_ != '/' || in_character_class) {
if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false;
if (c0_ < 0 || unicode_cache_->IsLineTerminator(c0_)) return false;
if (c0_ == '\\') { // Escape sequence.
AddLiteralCharAdvance();
if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false;
if (c0_ < 0 || unicode_cache_->IsLineTerminator(c0_)) return false;
AddLiteralCharAdvance();
// If the escape allows more characters, i.e., \x??, \u????, or \c?,
// only "safe" characters are allowed (letters, digits, underscore),
......@@ -1156,7 +1159,7 @@ bool Scanner::ScanLiteralUnicodeEscape() {
bool Scanner::ScanRegExpFlags() {
// Scan regular expression flags.
LiteralScope literal(this);
while (unicode_cache_->IsIdentifierPart(c0_)) {
while (c0_ >= 0 && unicode_cache_->IsIdentifierPart(c0_)) {
if (c0_ != '\\') {
AddLiteralCharAdvance();
} else {
......
......@@ -13,7 +13,7 @@ namespace unibrow {
template <class T, int s> bool Predicate<T, s>::get(uchar code_point) {
CacheEntry entry = entries_[code_point & kMask];
if (entry.code_point_ == code_point) return entry.value_;
if (entry.code_point() == code_point) return entry.value();
return CalculateValue(code_point);
}
......
......@@ -7,6 +7,7 @@
#include <sys/types.h>
#include "src/globals.h"
#include "src/utils.h"
/**
* \file
* Definitions and convenience functions for working with unicode.
......@@ -28,16 +29,26 @@ class Predicate {
public:
inline Predicate() { }
inline bool get(uchar c);
private:
friend class Test;
bool CalculateValue(uchar c);
struct CacheEntry {
inline CacheEntry() : code_point_(0), value_(0) { }
class CacheEntry {
public:
inline CacheEntry()
: bit_field_(CodePointField::encode(0) | ValueField::encode(0)) {}
inline CacheEntry(uchar code_point, bool value)
: code_point_(code_point),
value_(value) { }
uchar code_point_ : 21;
bool value_ : 1;
: bit_field_(CodePointField::encode(code_point) |
ValueField::encode(value)) {}
uchar code_point() const { return CodePointField::decode(bit_field_); }
bool value() const { return ValueField::decode(bit_field_); }
private:
class CodePointField : public v8::internal::BitField<uchar, 0, 21> {};
class ValueField : public v8::internal::BitField<bool, 21, 1> {};
uint32_t bit_field_;
};
static const int kSize = size;
static const int kMask = kSize - 1;
......
......@@ -230,6 +230,14 @@ class BitFieldBase {
};
template <class T, int shift, int size>
class BitField8 : public BitFieldBase<T, shift, size, uint8_t> {};
template <class T, int shift, int size>
class BitField16 : public BitFieldBase<T, shift, size, uint16_t> {};
template<class T, int shift, int size>
class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
......
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