Replace C++ bitfields with our own BitFields
authorjkummerow@chromium.org <jkummerow@chromium.org>
Wed, 5 Nov 2014 12:40:56 +0000 (12:40 +0000)
committerjkummerow@chromium.org <jkummerow@chromium.org>
Wed, 5 Nov 2014 12:41:46 +0000 (12:41 +0000)
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

15 files changed:
src/ast.cc
src/ast.h
src/heap-snapshot-generator-inl.h
src/heap-snapshot-generator.cc
src/heap-snapshot-generator.h
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/profile-generator-inl.h
src/profile-generator.cc
src/profile-generator.h
src/runtime/runtime-array.cc
src/scanner.cc
src/unicode-inl.h
src/unicode.h
src/utils.h

index 1df668d..26bc491 100644 (file)
@@ -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;
index aa23b4e..749e579 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -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_;
index 3f7e622..ad95776 100644 (file)
@@ -12,7 +12,7 @@ namespace internal {
 
 
 HeapEntry* HeapGraphEdge::from() const {
-  return &snapshot()->entries()[from_index_];
+  return &snapshot()->entries()[from_index()];
 }
 
 
index 68522fc..7f217bb 100644 (file)
@@ -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);
index 646d497..fb43876 100644 (file)
@@ -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.
index 188119d..ce76fbe 100644 (file)
@@ -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;
 }
 
index 810a2fd..5723d4a 100644 (file)
@@ -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_;
 };
 
 
index 58c124f..b638857 100644 (file)
 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) {
index 6017f12..4607156 100644 (file)
@@ -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);
 }
 
 
index 5ebb92b..f78beb0 100644 (file)
@@ -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_;
index c3a6d80..523d8f5 100644 (file)
@@ -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_;
 };
 
 
index 8062faa..e63239d 100644 (file)
@@ -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 {
index d47ee3e..0f78d39 100644 (file)
@@ -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);
 }
 
index 1af6170..1666814 100644 (file)
@@ -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;
index dcefa44..d5685c9 100644 (file)
@@ -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> { };