Reviewers: rossberg,
Message:
rossberg, ptal.
My efficiency fixes yesterday got reverted because they uncovered this bug;
after this fix I can reland them as is.
Description:
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.
[email protected]
BUG=
Please review this at https://codereview.chromium.org/699343004/
Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files (+22, -7 lines):
M src/ast-value-factory.h
M src/ast-value-factory.cc
Index: src/ast-value-factory.cc
diff --git a/src/ast-value-factory.cc b/src/ast-value-factory.cc
index
895ce39f652845fa83674d61ec98b0c9b8f1b5e1..2a98d07105b1fd4d02d5bb5ed01eec18f6e0db75
100644
--- a/src/ast-value-factory.cc
+++ b/src/ast-value-factory.cc
@@ -229,13 +229,28 @@ const AstRawString* AstValueFactory::GetTwoByteString(
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;
String::FlatContent content = literal->GetFlatContent();
if (content.IsOneByte()) {
- return GetOneByteString(content.ToOneByteVector());
+ Vector<const uint8_t> literal = content.ToOneByteVector();
+ uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
+ literal.start(), literal.length(), hash_seed_);
+ result = GetString(hash, true, literal);
+ } else {
+ DCHECK(content.IsTwoByte());
+ Vector<const uint16_t> literal = content.ToUC16Vector();
+ uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
+ literal.start(), literal.length(), hash_seed_);
+ result = GetString(hash, false, Vector<const byte>::cast(literal));
}
- DCHECK(content.IsTwoByte());
- return GetTwoByteString(content.ToUC16Vector());
+ isolate_ = saved_isolate;
+ result->string_ = literal;
+ return result;
}
@@ -348,8 +363,8 @@ const AstValue* AstValueFactory::NewTheHole() {
#undef GENERATE_VALUE_GETTER
-const AstRawString* AstValueFactory::GetString(
- uint32_t hash, bool is_one_byte, Vector<const byte> literal_bytes) {
+AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte,
+ Vector<const byte> literal_bytes)
{
// literal_bytes here points to whatever the user passed, and this is OK
// because we use vector_compare (which checks the contents) to compare
// against the AstRawStrings which are in the string_table_. We should
not
Index: src/ast-value-factory.h
diff --git a/src/ast-value-factory.h b/src/ast-value-factory.h
index
071ca9ce9cc18abf23e17f09c31e69ca69a8ccce..b8fc30a77c564fe67deaaf9c081006f22787ff37
100644
--- a/src/ast-value-factory.h
+++ b/src/ast-value-factory.h
@@ -327,8 +327,8 @@ class AstValueFactory {
const AstValue* NewTheHole();
private:
- const AstRawString* GetString(uint32_t hash, bool is_one_byte,
- Vector<const byte> literal_bytes);
+ 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).
HashMap string_table_;
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.