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