Replace C++ bitfields with our own BitFields

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

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

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

Cr-Commit-Position: refs/heads/master@{#25148}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25148 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 66430307
......@@ -61,9 +61,9 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const {
VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
: Expression(zone, position),
is_this_(var->is_this()),
is_assigned_(false),
is_resolved_(false),
bit_field_(IsThisField::encode(var->is_this()) |
IsAssignedField::encode(false) |
IsResolvedField::encode(false)),
variable_feedback_slot_(FeedbackVectorICSlot::Invalid()),
raw_name_(var->raw_name()),
interface_(var->interface()) {
......@@ -74,9 +74,8 @@ VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
VariableProxy::VariableProxy(Zone* zone, const AstRawString* name, bool is_this,
Interface* interface, int position)
: Expression(zone, position),
is_this_(is_this),
is_assigned_(false),
is_resolved_(false),
bit_field_(IsThisField::encode(is_this) | IsAssignedField::encode(false) |
IsResolvedField::encode(false)),
variable_feedback_slot_(FeedbackVectorICSlot::Invalid()),
raw_name_(name),
interface_(interface) {}
......@@ -99,17 +98,17 @@ void VariableProxy::BindTo(Variable* var) {
Assignment::Assignment(Zone* zone, Token::Value op, Expression* target,
Expression* value, int pos)
: Expression(zone, pos),
is_uninitialized_(false),
key_type_(ELEMENT),
store_mode_(STANDARD_STORE),
op_(op),
bit_field_(IsUninitializedField::encode(false) |
KeyTypeField::encode(ELEMENT) |
StoreModeField::encode(STANDARD_STORE) |
TokenField::encode(op)),
target_(target),
value_(value),
binary_operation_(NULL) {}
Token::Value Assignment::binary_op() const {
switch (op_) {
switch (op()) {
case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
......
This diff is collapsed.
......@@ -12,7 +12,7 @@ namespace internal {
HeapEntry* HeapGraphEdge::from() const {
return &snapshot()->entries()[from_index_];
return &snapshot()->entries()[from_index()];
}
......
......@@ -18,8 +18,7 @@ namespace internal {
HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to)
: type_(type),
from_index_(from),
: bit_field_(TypeField::encode(type) | FromIndexField::encode(from)),
to_index_(to),
name_(name) {
DCHECK(type == kContextVariable
......@@ -31,8 +30,7 @@ HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to)
HeapGraphEdge::HeapGraphEdge(Type type, int index, int from, int to)
: type_(type),
from_index_(from),
: bit_field_(TypeField::encode(type) | FromIndexField::encode(from)),
to_index_(to),
index_(index) {
DCHECK(type == kElement || type == kHidden);
......
......@@ -28,22 +28,18 @@ class HeapGraphEdge BASE_EMBEDDED {
kWeak = v8::HeapGraphEdge::kWeak
};
HeapGraphEdge() { }
HeapGraphEdge(Type type, const char* name, int from, int to);
HeapGraphEdge(Type type, int index, int from, int to);
void ReplaceToIndexWithEntry(HeapSnapshot* snapshot);
Type type() const { return static_cast<Type>(type_); }
Type type() const { return TypeField::decode(bit_field_); }
int index() const {
DCHECK(type_ == kElement || type_ == kHidden);
DCHECK(type() == kElement || type() == kHidden);
return index_;
}
const char* name() const {
DCHECK(type_ == kContextVariable
|| type_ == kProperty
|| type_ == kInternal
|| type_ == kShortcut
|| type_ == kWeak);
DCHECK(type() == kContextVariable || type() == kProperty ||
type() == kInternal || type() == kShortcut || type() == kWeak);
return name_;
}
INLINE(HeapEntry* from() const);
......@@ -51,9 +47,11 @@ class HeapGraphEdge BASE_EMBEDDED {
private:
INLINE(HeapSnapshot* snapshot() const);
int from_index() const { return FromIndexField::decode(bit_field_); }
unsigned type_ : 3;
int from_index_ : 29;
class TypeField : public BitField<Type, 0, 3> {};
class FromIndexField : public BitField<int, 3, 29> {};
uint32_t bit_field_;
union {
// During entries population |to_index_| is used for storing the index,
// afterwards it is replaced with a pointer to the entry.
......
This diff is collapsed.
This diff is collapsed.
......@@ -10,14 +10,11 @@
namespace v8 {
namespace internal {
CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
const char* name,
const char* name_prefix,
const char* resource_name,
int line_number,
int column_number)
: tag_(tag),
builtin_id_(Builtins::builtin_count),
CodeEntry::CodeEntry(Logger::LogEventsAndTags tag, const char* name,
const char* name_prefix, const char* resource_name,
int line_number, int column_number)
: bit_field_(TagField::encode(tag) |
BuiltinIdField::encode(Builtins::builtin_count)),
name_prefix_(name_prefix),
name_(name),
resource_name_(resource_name),
......@@ -26,7 +23,7 @@ CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
shared_id_(0),
script_id_(v8::UnboundScript::kNoScriptId),
no_frame_ranges_(NULL),
bailout_reason_(kEmptyBailoutReason) { }
bailout_reason_(kEmptyBailoutReason) {}
bool CodeEntry::is_js_function_tag(Logger::LogEventsAndTags tag) {
......
......@@ -143,7 +143,7 @@ CodeEntry::~CodeEntry() {
uint32_t CodeEntry::GetCallUid() const {
uint32_t hash = ComputeIntegerHash(tag_, v8::internal::kZeroHashSeed);
uint32_t hash = ComputeIntegerHash(tag(), v8::internal::kZeroHashSeed);
if (shared_id_ != 0) {
hash ^= ComputeIntegerHash(static_cast<uint32_t>(shared_id_),
v8::internal::kZeroHashSeed);
......@@ -164,20 +164,18 @@ uint32_t CodeEntry::GetCallUid() const {
bool CodeEntry::IsSameAs(CodeEntry* entry) const {
return this == entry
|| (tag_ == entry->tag_
&& shared_id_ == entry->shared_id_
&& (shared_id_ != 0
|| (name_prefix_ == entry->name_prefix_
&& name_ == entry->name_
&& resource_name_ == entry->resource_name_
&& line_number_ == entry->line_number_)));
return this == entry ||
(tag() == entry->tag() && shared_id_ == entry->shared_id_ &&
(shared_id_ != 0 ||
(name_prefix_ == entry->name_prefix_ && name_ == entry->name_ &&
resource_name_ == entry->resource_name_ &&
line_number_ == entry->line_number_)));
}
void CodeEntry::SetBuiltinId(Builtins::Name id) {
tag_ = Logger::BUILTIN_TAG;
builtin_id_ = id;
bit_field_ = TagField::update(bit_field_, Logger::BUILTIN_TAG);
bit_field_ = BuiltinIdField::update(bit_field_, id);
}
......
......@@ -55,7 +55,7 @@ class CodeEntry {
int column_number = v8::CpuProfileNode::kNoColumnNumberInfo);
~CodeEntry();
bool is_js_function() const { return is_js_function_tag(tag_); }
bool is_js_function() const { return is_js_function_tag(tag()); }
const char* name_prefix() const { return name_prefix_; }
bool has_name_prefix() const { return name_prefix_[0] != '\0'; }
const char* name() const { return name_; }
......@@ -78,7 +78,9 @@ class CodeEntry {
}
void SetBuiltinId(Builtins::Name id);
Builtins::Name builtin_id() const { return builtin_id_; }
Builtins::Name builtin_id() const {
return BuiltinIdField::decode(bit_field_);
}
uint32_t GetCallUid() const;
bool IsSameAs(CodeEntry* entry) const;
......@@ -88,8 +90,11 @@ class CodeEntry {
static const char* const kEmptyBailoutReason;
private:
Logger::LogEventsAndTags tag_ : 8;
Builtins::Name builtin_id_ : 8;
class TagField : public BitField<Logger::LogEventsAndTags, 0, 8> {};
class BuiltinIdField : public BitField<Builtins::Name, 8, 8> {};
Logger::LogEventsAndTags tag() const { return TagField::decode(bit_field_); }
uint32_t bit_field_;
const char* name_prefix_;
const char* name_;
const char* resource_name_;
......
......@@ -104,19 +104,19 @@ class ArrayConcatVisitor {
storage_(Handle<FixedArray>::cast(
isolate->global_handles()->Create(*storage))),
index_offset_(0u),
fast_elements_(fast_elements),
exceeds_array_limit_(false) {}
bit_field_(FastElementsField::encode(fast_elements) |
ExceedsLimitField::encode(false)) {}
~ArrayConcatVisitor() { clear_storage(); }
void visit(uint32_t i, Handle<Object> elm) {
if (i > JSObject::kMaxElementCount - index_offset_) {
exceeds_array_limit_ = true;
set_exceeds_array_limit(true);
return;
}
uint32_t index = index_offset_ + i;
if (fast_elements_) {
if (fast_elements()) {
if (index < static_cast<uint32_t>(storage_->length())) {
storage_->set(index, *elm);
return;
......@@ -128,7 +128,7 @@ class ArrayConcatVisitor {
SetDictionaryMode();
// Fall-through to dictionary mode.
}
DCHECK(!fast_elements_);
DCHECK(!fast_elements());
Handle<SeededNumberDictionary> dict(
SeededNumberDictionary::cast(*storage_));
Handle<SeededNumberDictionary> result =
......@@ -149,21 +149,23 @@ class ArrayConcatVisitor {
// If the initial length estimate was off (see special case in visit()),
// but the array blowing the limit didn't contain elements beyond the
// provided-for index range, go to dictionary mode now.
if (fast_elements_ &&
if (fast_elements() &&
index_offset_ >
static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
SetDictionaryMode();
}
}
bool exceeds_array_limit() { return exceeds_array_limit_; }
bool exceeds_array_limit() const {
return ExceedsLimitField::decode(bit_field_);
}
Handle<JSArray> ToArray() {
Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
Handle<Object> length =
isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
Handle<Map> map = JSObject::GetElementsTransitionMap(
array, fast_elements_ ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
array->set_map(*map);
array->set_length(*length);
array->set_elements(*storage_);
......@@ -173,7 +175,7 @@ class ArrayConcatVisitor {
private:
// Convert storage to dictionary mode.
void SetDictionaryMode() {
DCHECK(fast_elements_);
DCHECK(fast_elements());
Handle<FixedArray> current_storage(*storage_);
Handle<SeededNumberDictionary> slow_storage(
SeededNumberDictionary::New(isolate_, current_storage->length()));
......@@ -191,7 +193,7 @@ class ArrayConcatVisitor {
}
clear_storage();
set_storage(*slow_storage);
fast_elements_ = false;
set_fast_elements(false);
}
inline void clear_storage() {
......@@ -203,13 +205,23 @@ class ArrayConcatVisitor {
Handle<FixedArray>::cast(isolate_->global_handles()->Create(storage));
}
class FastElementsField : public BitField<bool, 0, 1> {};
class ExceedsLimitField : public BitField<bool, 1, 1> {};
bool fast_elements() const { return FastElementsField::decode(bit_field_); }
void set_fast_elements(bool fast) {
bit_field_ = FastElementsField::update(bit_field_, fast);
}
void set_exceeds_array_limit(bool exceeds) {
bit_field_ = ExceedsLimitField::update(bit_field_, exceeds);
}
Isolate* isolate_;
Handle<FixedArray> storage_; // Always a global handle.
// Index after last seen index. Always less than or equal to
// JSObject::kMaxElementCount.
uint32_t index_offset_;
bool fast_elements_ : 1;
bool exceeds_array_limit_ : 1;
uint32_t bit_field_;
};
......
......@@ -245,6 +245,8 @@ bool Scanner::SkipWhiteSpace() {
while (true) {
while (true) {
// The unicode cache accepts unsigned inputs.
if (c0_ < 0) break;
// Advance as long as character is a WhiteSpace or LineTerminator.
// Remember if the latter is the case.
if (unicode_cache_->IsLineTerminator(c0_)) {
......@@ -365,7 +367,7 @@ Token::Value Scanner::SkipMultiLineComment() {
while (c0_ >= 0) {
uc32 ch = c0_;
Advance();
if (unicode_cache_->IsLineTerminator(ch)) {
if (c0_ >= 0 && unicode_cache_->IsLineTerminator(ch)) {
// Following ECMA-262, section 7.4, a comment containing
// a newline will make the comment count as a line-terminator.
has_multiline_comment_before_next_ = true;
......@@ -625,14 +627,14 @@ void Scanner::Scan() {
break;
default:
if (unicode_cache_->IsIdentifierStart(c0_)) {
if (c0_ < 0) {
token = Token::EOS;
} else if (unicode_cache_->IsIdentifierStart(c0_)) {
token = ScanIdentifierOrKeyword();
} else if (IsDecimalDigit(c0_)) {
token = ScanNumber(false);
} else if (SkipWhiteSpace()) {
token = Token::WHITESPACE;
} else if (c0_ < 0) {
token = Token::EOS;
} else {
token = Select(Token::ILLEGAL);
}
......@@ -674,7 +676,7 @@ bool Scanner::ScanEscape() {
Advance();
// Skip escaped newlines.
if (unicode_cache_->IsLineTerminator(c)) {
if (c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) {
// Allow CR+LF newlines in multiline string literals.
if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
// Allow LF+CR newlines in multiline string literals.
......@@ -871,7 +873,8 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
// not be an identifier start or a decimal digit; see ECMA-262
// section 7.8.3, page 17 (note that we read only one decimal digit
// if the value is 0).
if (IsDecimalDigit(c0_) || unicode_cache_->IsIdentifierStart(c0_))
if (IsDecimalDigit(c0_) ||
(c0_ >= 0 && unicode_cache_->IsIdentifierStart(c0_)))
return Token::ILLEGAL;
literal.Complete();
......@@ -1039,7 +1042,7 @@ Token::Value Scanner::ScanIdentifierOrKeyword() {
AddLiteralChar(first_char);
// Scan the rest of the identifier characters.
while (unicode_cache_->IsIdentifierPart(c0_)) {
while (c0_ >= 0 && unicode_cache_->IsIdentifierPart(c0_)) {
if (c0_ != '\\') {
uc32 next_char = c0_;
Advance();
......@@ -1067,7 +1070,7 @@ Token::Value Scanner::ScanIdentifierOrKeyword() {
Token::Value Scanner::ScanIdentifierSuffix(LiteralScope* literal) {
// Scan the rest of the identifier characters.
while (unicode_cache_->IsIdentifierPart(c0_)) {
while (c0_ >= 0 && unicode_cache_->IsIdentifierPart(c0_)) {
if (c0_ == '\\') {
uc32 c = ScanIdentifierUnicodeEscape();
// Only allow legal identifier part characters.
......@@ -1106,10 +1109,10 @@ bool Scanner::ScanRegExpPattern(bool seen_equal) {
}
while (c0_ != '/' || in_character_class) {
if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false;
if (c0_ < 0 || unicode_cache_->IsLineTerminator(c0_)) return false;
if (c0_ == '\\') { // Escape sequence.
AddLiteralCharAdvance();
if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false;
if (c0_ < 0 || unicode_cache_->IsLineTerminator(c0_)) return false;
AddLiteralCharAdvance();
// If the escape allows more characters, i.e., \x??, \u????, or \c?,
// only "safe" characters are allowed (letters, digits, underscore),
......@@ -1156,7 +1159,7 @@ bool Scanner::ScanLiteralUnicodeEscape() {
bool Scanner::ScanRegExpFlags() {
// Scan regular expression flags.
LiteralScope literal(this);
while (unicode_cache_->IsIdentifierPart(c0_)) {
while (c0_ >= 0 && unicode_cache_->IsIdentifierPart(c0_)) {
if (c0_ != '\\') {
AddLiteralCharAdvance();
} else {
......
......@@ -13,7 +13,7 @@ namespace unibrow {
template <class T, int s> bool Predicate<T, s>::get(uchar code_point) {
CacheEntry entry = entries_[code_point & kMask];
if (entry.code_point_ == code_point) return entry.value_;
if (entry.code_point() == code_point) return entry.value();
return CalculateValue(code_point);
}
......
......@@ -7,6 +7,7 @@
#include <sys/types.h>
#include "src/globals.h"
#include "src/utils.h"
/**
* \file
* Definitions and convenience functions for working with unicode.
......@@ -28,16 +29,26 @@ class Predicate {
public:
inline Predicate() { }
inline bool get(uchar c);
private:
friend class Test;
bool CalculateValue(uchar c);
struct CacheEntry {
inline CacheEntry() : code_point_(0), value_(0) { }
class CacheEntry {
public:
inline CacheEntry()
: bit_field_(CodePointField::encode(0) | ValueField::encode(0)) {}
inline CacheEntry(uchar code_point, bool value)
: code_point_(code_point),
value_(value) { }
uchar code_point_ : 21;
bool value_ : 1;
: bit_field_(CodePointField::encode(code_point) |
ValueField::encode(value)) {}
uchar code_point() const { return CodePointField::decode(bit_field_); }
bool value() const { return ValueField::decode(bit_field_); }
private:
class CodePointField : public v8::internal::BitField<uchar, 0, 21> {};
class ValueField : public v8::internal::BitField<bool, 21, 1> {};
uint32_t bit_field_;
};
static const int kSize = size;
static const int kMask = kSize - 1;
......
......@@ -230,6 +230,14 @@ class BitFieldBase {
};
template <class T, int shift, int size>
class BitField8 : public BitFieldBase<T, shift, size, uint8_t> {};
template <class T, int shift, int size>
class BitField16 : public BitFieldBase<T, shift, size, uint16_t> {};
template<class T, int shift, int size>
class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment