28 #include "src/ast/ast-value-factory.h" 30 #include "src/char-predicates-inl.h" 31 #include "src/objects-inl.h" 32 #include "src/objects.h" 33 #include "src/string-hasher.h" 34 #include "src/utils-inl.h" 42 class OneByteStringStream {
44 explicit OneByteStringStream(Vector<const byte> lb) :
45 literal_bytes_(lb), pos_(0) {}
47 bool HasMore() {
return pos_ < literal_bytes_.length(); }
48 uint16_t GetNext() {
return literal_bytes_[pos_++]; }
51 Vector<const byte> literal_bytes_;
62 bool IsMatch(
Object* other)
override {
63 if (string_->is_one_byte())
64 return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
65 return String::cast(other)->IsTwoByteEqualTo(
70 if (string_->is_one_byte())
71 return isolate->factory()->NewOneByteInternalizedString(
72 string_->literal_bytes_, string_->hash_field());
73 return isolate->factory()->NewTwoByteInternalizedString(
75 string_->hash_field());
82 void AstRawString::Internalize(
Isolate* isolate) {
84 if (literal_bytes_.length() == 0) {
85 set_string(isolate->factory()->empty_string());
87 AstRawStringInternalizationKey key(
this);
88 set_string(StringTable::LookupKey(isolate, &key));
92 bool AstRawString::AsArrayIndex(
uint32_t* index)
const {
95 if ((hash_field_ & Name::kIsNotArrayIndexMask) != 0)
return false;
96 if (length() <= Name::kMaxCachedArrayIndexLength) {
97 *index = Name::ArrayIndexValueBits::decode(hash_field_);
99 OneByteStringStream stream(literal_bytes_);
100 CHECK(StringToArrayIndex(&stream, index));
105 bool AstRawString::IsOneByteEqualTo(
const char* data)
const {
106 if (!is_one_byte())
return false;
108 size_t length =
static_cast<size_t>(literal_bytes_.length());
109 if (length != strlen(data))
return false;
111 return 0 == strncmp(reinterpret_cast<const char*>(literal_bytes_.start()),
115 uint16_t AstRawString::FirstCharacter()
const {
116 if (is_one_byte())
return literal_bytes_[0];
117 const uint16_t* c =
reinterpret_cast<const uint16_t*
>(literal_bytes_.start());
121 bool AstRawString::Compare(
void* a,
void* b) {
122 const AstRawString* lhs =
static_cast<AstRawString*
>(a);
123 const AstRawString* rhs =
static_cast<AstRawString*
>(b);
124 DCHECK_EQ(lhs->Hash(), rhs->Hash());
126 if (lhs->length() != rhs->length())
return false;
127 const unsigned char* l = lhs->raw_data();
128 const unsigned char* r = rhs->raw_data();
129 size_t length = rhs->length();
130 if (lhs->is_one_byte()) {
131 if (rhs->is_one_byte()) {
132 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
133 reinterpret_cast<const uint8_t*>(r),
136 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
137 reinterpret_cast<const uint16_t*>(r),
141 if (rhs->is_one_byte()) {
142 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
143 reinterpret_cast<const uint8_t*>(r),
146 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
147 reinterpret_cast<const uint16_t*>(r),
153 void AstConsString::Internalize(Isolate* isolate) {
155 set_string(isolate->factory()->empty_string());
160 Handle<String> tmp(segment_.string->string());
161 for (AstConsString::Segment* current = segment_.next; current !=
nullptr;
162 current = current->next) {
163 tmp = isolate->factory()
164 ->NewConsString(current->string->string(), tmp)
170 std::forward_list<const AstRawString*> AstConsString::ToRawStrings()
const {
171 std::forward_list<const AstRawString*> result;
176 result.emplace_front(segment_.string);
177 for (AstConsString::Segment* current = segment_.next; current !=
nullptr;
178 current = current->next) {
179 result.emplace_front(current->string);
184 AstStringConstants::AstStringConstants(Isolate* isolate, uint64_t hash_seed)
185 : zone_(isolate->allocator(), ZONE_NAME),
186 string_table_(AstRawString::Compare),
187 hash_seed_(hash_seed) {
188 DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
189 #define F(name, str) \ 191 const char* data = str; \ 192 Vector<const uint8_t> literal(reinterpret_cast<const uint8_t*>(data), \ 193 static_cast<int>(strlen(data))); \ 194 uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>( \ 195 literal.start(), literal.length(), hash_seed_); \ 196 name##_string_ = new (&zone_) AstRawString(true, literal, hash_field); \ 199 name##_string_->set_string(isolate->factory()->name##_string()); \ 200 base::HashMap::Entry* entry = \ 201 string_table_.InsertNew(name##_string_, name##_string_->Hash()); \ 202 DCHECK_NULL(entry->value); \ 203 entry->value = reinterpret_cast<void*>(1); \ 205 AST_STRING_CONSTANTS(F)
209 AstRawString* AstValueFactory::GetOneByteStringInternal(
210 Vector<const uint8_t> literal) {
211 if (literal.length() == 1 && literal[0] < kMaxOneCharStringValue) {
212 int key = literal[0];
213 if (V8_UNLIKELY(one_character_strings_[key] ==
nullptr)) {
214 uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
215 literal.start(), literal.length(), hash_seed_);
216 one_character_strings_[key] = GetString(hash_field,
true, literal);
218 return one_character_strings_[key];
220 uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>(
221 literal.start(), literal.length(), hash_seed_);
222 return GetString(hash_field,
true, literal);
225 AstRawString* AstValueFactory::GetTwoByteStringInternal(
226 Vector<const uint16_t> literal) {
227 uint32_t hash_field = StringHasher::HashSequentialString<uint16_t>(
228 literal.start(), literal.length(), hash_seed_);
229 return GetString(hash_field,
false, Vector<const byte>::cast(literal));
232 const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
233 AstRawString* result =
nullptr;
234 DisallowHeapAllocation no_gc;
235 String::FlatContent content = literal->GetFlatContent();
236 if (content.IsOneByte()) {
237 result = GetOneByteStringInternal(content.ToOneByteVector());
239 DCHECK(content.IsTwoByte());
240 result = GetTwoByteStringInternal(content.ToUC16Vector());
245 const AstRawString* AstValueFactory::CloneFromOtherFactory(
246 const AstRawString* raw_string) {
247 const AstRawString* result = GetString(
248 raw_string->hash_field(), raw_string->is_one_byte(),
249 Vector<const byte>(raw_string->raw_data(), raw_string->byte_length()));
253 AstConsString* AstValueFactory::NewConsString() {
254 AstConsString* new_string =
new (zone_) AstConsString;
255 DCHECK_NOT_NULL(new_string);
256 AddConsString(new_string);
260 AstConsString* AstValueFactory::NewConsString(
const AstRawString* str) {
261 return NewConsString()->AddString(zone_, str);
264 AstConsString* AstValueFactory::NewConsString(
const AstRawString* str1,
265 const AstRawString* str2) {
266 return NewConsString()->AddString(zone_, str1)->AddString(zone_, str2);
269 void AstValueFactory::Internalize(Isolate* isolate) {
272 for (AstRawString* current = strings_; current !=
nullptr;) {
273 AstRawString* next = current->next();
274 current->Internalize(isolate);
279 for (AstConsString* current = cons_strings_; current !=
nullptr;) {
280 AstConsString* next = current->next();
281 current->Internalize(isolate);
288 AstRawString* AstValueFactory::GetString(
uint32_t hash_field,
bool is_one_byte,
289 Vector<const byte> literal_bytes) {
294 AstRawString key(is_one_byte, literal_bytes, hash_field);
295 base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, key.Hash());
296 if (entry->value ==
nullptr) {
298 int length = literal_bytes.length();
299 byte* new_literal_bytes = zone_->NewArray<byte>(length);
300 memcpy(new_literal_bytes, literal_bytes.start(), length);
301 AstRawString* new_string =
new (zone_) AstRawString(
302 is_one_byte, Vector<const byte>(new_literal_bytes, length), hash_field);
303 CHECK_NOT_NULL(new_string);
304 AddString(new_string);
305 entry->key = new_string;
306 entry->value =
reinterpret_cast<void*
>(1);
308 return reinterpret_cast<AstRawString*
>(entry->key);