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()) {
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) {}
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;
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.
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; }
: 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());
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.
};
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_; }
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_
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 {
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();
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) {}
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_;
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;
}
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; }
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_;
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_; }
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,
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);
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_;
HeapEntry* HeapGraphEdge::from() const {
- return &snapshot()->entries()[from_index_];
+ return &snapshot()->entries()[from_index()];
}
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
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);
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);
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.
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;
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());
env->Push(value);
}
}
- done_with_replay_ = true;
+ set_done_with_replay();
}
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.
}
}
-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();
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;
}
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);
}
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.
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;
}
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();
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_;
};
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
}
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);
}
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_;
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);
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;
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.
}
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.
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_;
};
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 {
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_;
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
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(); }
}
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());
}
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());
}
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());
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
// 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_;
};
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>
} 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();
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()) {
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);
}
}
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() ||
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_;
};
}
DCHECK_EQ(index, 2);
- return RequiredValueRepresentation(elements_kind_, store_mode_);
+ return RequiredValueRepresentation(elements_kind(), store_mode());
}
static Representation RequiredValueRepresentation(
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;
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() {
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);
}
}
- 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_;
};
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);
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_;
};
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),
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) {
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);
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);
}
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_; }
}
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;
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_;
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;
SetDictionaryMode();
// Fall-through to dictionary mode.
}
- DCHECK(!fast_elements_);
+ DCHECK(!fast_elements());
Handle<SeededNumberDictionary> dict(
SeededNumberDictionary::cast(*storage_));
Handle<SeededNumberDictionary> result =
// 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_);
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()));
}
clear_storage();
set_storage(*slow_storage);
- fast_elements_ = false;
+ set_fast_elements(false);
}
inline void clear_storage() {
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_;
};
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_)) {
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;
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);
}
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.
// 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();
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();
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.
}
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),
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 {
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);
}
#include <sys/types.h>
#include "src/globals.h"
+#include "src/utils.h"
/**
* \file
* Definitions and convenience functions for working with unicode.
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;
};
+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> { };