Commit dddeb98d authored by marja@chromium.org's avatar marja@chromium.org

Parser & internalization fix: ensure no heap allocs during GetString(Handle<String>).

The bug has always been there: when the parser is operating in the "immediately
internalize" mode and calls GetString, we get FlatContent of a string and then
do heap allocation.

The bug was uncovered by https://codereview.chromium.org/693803004/ (which put
the parser to the "immediately internalize" mode more often), but looking at the
code, it's possible that it can happen in other cases too.

This CL makes AstValueFactory handle this situation gracefully: it won't try to
internalize inside GetString(Handle<String>); it's unnecessary anyway since we
have the Handle<String> already.

R=rossberg@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#25155}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25155 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 73835421
...@@ -212,7 +212,7 @@ void AstValue::Internalize(Isolate* isolate) { ...@@ -212,7 +212,7 @@ void AstValue::Internalize(Isolate* isolate) {
} }
const AstRawString* AstValueFactory::GetOneByteString( AstRawString* AstValueFactory::GetOneByteStringInternal(
Vector<const uint8_t> literal) { Vector<const uint8_t> literal) {
uint32_t hash = StringHasher::HashSequentialString<uint8_t>( uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
literal.start(), literal.length(), hash_seed_); literal.start(), literal.length(), hash_seed_);
...@@ -220,7 +220,7 @@ const AstRawString* AstValueFactory::GetOneByteString( ...@@ -220,7 +220,7 @@ const AstRawString* AstValueFactory::GetOneByteString(
} }
const AstRawString* AstValueFactory::GetTwoByteString( AstRawString* AstValueFactory::GetTwoByteStringInternal(
Vector<const uint16_t> literal) { Vector<const uint16_t> literal) {
uint32_t hash = StringHasher::HashSequentialString<uint16_t>( uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
literal.start(), literal.length(), hash_seed_); literal.start(), literal.length(), hash_seed_);
...@@ -229,13 +229,22 @@ const AstRawString* AstValueFactory::GetTwoByteString( ...@@ -229,13 +229,22 @@ const AstRawString* AstValueFactory::GetTwoByteString(
const AstRawString* AstValueFactory::GetString(Handle<String> literal) { const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
// For the FlatContent to stay valid, we shouldn't do any heap
// allocation. Make sure we won't try to internalize the string in GetString.
AstRawString* result = NULL;
Isolate* saved_isolate = isolate_;
isolate_ = NULL;
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
String::FlatContent content = literal->GetFlatContent(); String::FlatContent content = literal->GetFlatContent();
if (content.IsOneByte()) { if (content.IsOneByte()) {
return GetOneByteString(content.ToOneByteVector()); result = GetOneByteStringInternal(content.ToOneByteVector());
} else {
DCHECK(content.IsTwoByte());
result = GetTwoByteStringInternal(content.ToUC16Vector());
} }
DCHECK(content.IsTwoByte()); isolate_ = saved_isolate;
return GetTwoByteString(content.ToUC16Vector()); result->string_ = literal;
return result;
} }
...@@ -348,8 +357,8 @@ const AstValue* AstValueFactory::NewTheHole() { ...@@ -348,8 +357,8 @@ const AstValue* AstValueFactory::NewTheHole() {
#undef GENERATE_VALUE_GETTER #undef GENERATE_VALUE_GETTER
const AstRawString* AstValueFactory::GetString( AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte,
uint32_t hash, bool is_one_byte, Vector<const byte> literal_bytes) { Vector<const byte> literal_bytes) {
// literal_bytes here points to whatever the user passed, and this is OK // literal_bytes here points to whatever the user passed, and this is OK
// because we use vector_compare (which checks the contents) to compare // because we use vector_compare (which checks the contents) to compare
// against the AstRawStrings which are in the string_table_. We should not // against the AstRawStrings which are in the string_table_. We should not
......
...@@ -287,12 +287,16 @@ class AstValueFactory { ...@@ -287,12 +287,16 @@ class AstValueFactory {
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
const AstRawString* GetOneByteString(Vector<const uint8_t> literal); const AstRawString* GetOneByteString(Vector<const uint8_t> literal) {
return GetOneByteStringInternal(literal);
}
const AstRawString* GetOneByteString(const char* string) { const AstRawString* GetOneByteString(const char* string) {
return GetOneByteString(Vector<const uint8_t>( return GetOneByteString(Vector<const uint8_t>(
reinterpret_cast<const uint8_t*>(string), StrLength(string))); reinterpret_cast<const uint8_t*>(string), StrLength(string)));
} }
const AstRawString* GetTwoByteString(Vector<const uint16_t> literal); const AstRawString* GetTwoByteString(Vector<const uint16_t> literal) {
return GetTwoByteStringInternal(literal);
}
const AstRawString* GetString(Handle<String> literal); const AstRawString* GetString(Handle<String> literal);
const AstConsString* NewConsString(const AstString* left, const AstConsString* NewConsString(const AstString* left,
const AstString* right); const AstString* right);
...@@ -327,8 +331,10 @@ class AstValueFactory { ...@@ -327,8 +331,10 @@ class AstValueFactory {
const AstValue* NewTheHole(); const AstValue* NewTheHole();
private: private:
const AstRawString* GetString(uint32_t hash, bool is_one_byte, AstRawString* GetOneByteStringInternal(Vector<const uint8_t> literal);
Vector<const byte> literal_bytes); AstRawString* GetTwoByteStringInternal(Vector<const uint16_t> literal);
AstRawString* GetString(uint32_t hash, bool is_one_byte,
Vector<const byte> literal_bytes);
// All strings are copied here, one after another (no NULLs inbetween). // All strings are copied here, one after another (no NULLs inbetween).
HashMap string_table_; HashMap string_table_;
......
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