Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1284)

Unified Diff: src/json-parser.h

Issue 7977001: Added ability to lock strings to prevent their representation or encoding from changing. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix bug in test when running threaded. Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap.cc ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/json-parser.h
diff --git a/src/json-parser.h b/src/json-parser.h
index ca796a69907e090363180d9500cac4797387b916..66478938f41d5c619b8d8638a6805e2f170a4893 100644
--- a/src/json-parser.h
+++ b/src/json-parser.h
@@ -39,28 +39,45 @@
namespace v8 {
namespace internal {
-// A simple json parser.
-template <bool seq_ascii>
+// A simple JSON parser.
+template <typename StringType>
class JsonParser BASE_EMBEDDED {
public:
static Handle<Object> Parse(Handle<String> source) {
- return JsonParser().ParseJson(source);
+ return JsonParser(Handle<StringType>::cast(source)).ParseJson();
}
static const int kEndOfString = -1;
private:
- // Parse a string containing a single JSON value.
- Handle<Object> ParseJson(Handle<String> source);
+ typedef typename StringType::CharType SourceChar;
+
+ explicit JsonParser(Handle<StringType> source)
+ : isolate_(source->GetHeap()->isolate()),
+ source_(source),
+ characters_(NULL),
+ source_length_(source->length()),
+ position_(-1) {
+ InitializeSource();
+ }
+
+
+ // Parse the source string as containing a single JSON value.
+ Handle<Object> ParseJson();
+
+ // Set up the object so GetChar works, in case it needs more than just
+ // the constructor.
+ void InitializeSource();
+
+ inline uc32 GetChar(int position);
+ inline const SourceChar* GetChars();
inline void Advance() {
position_++;
if (position_ >= source_length_) {
c0_ = kEndOfString;
- } else if (seq_ascii) {
- c0_ = seq_source_->SeqAsciiStringGet(position_);
} else {
- c0_ = source_->Get(position_);
+ c0_ = GetChar(position_);
}
}
@@ -68,14 +85,20 @@ class JsonParser BASE_EMBEDDED {
// section 15.12.1.1. The only allowed whitespace characters between tokens
// are tab, carriage-return, newline and space.
+
+ static inline bool IsJsonWhitespace(uc32 ch) {
+ const char* whitespaces = "\x20\x09\x0a\0\0\x0d\0\0";
+ return (static_cast<uc32>(whitespaces[ch & 0x07]) == ch);
+ }
+
inline void AdvanceSkipWhitespace() {
do {
Advance();
- } while (c0_ == '\t' || c0_ == '\r' || c0_ == '\n' || c0_ == ' ');
+ } while (IsJsonWhitespace(c0_));
}
inline void SkipWhitespace() {
- while (c0_ == '\t' || c0_ == '\r' || c0_ == '\n' || c0_ == ' ') {
+ while (IsJsonWhitespace(c0_)) {
Advance();
}
}
@@ -110,7 +133,7 @@ class JsonParser BASE_EMBEDDED {
// Creates a new string and copies prefix[start..end] into the beginning
// of it. Then scans the rest of the string, adding characters after the
// prefix. Called by ScanJsonString when reaching a '\' or non-ASCII char.
- template <typename StringType, typename SinkChar>
+ template <typename SinkStringType>
Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end);
// A JSON number (production JSONNumber) is a subset of the valid JavaScript
@@ -152,37 +175,26 @@ class JsonParser BASE_EMBEDDED {
static const int kInitialSpecialStringLength = 1024;
-
- private:
- Handle<String> source_;
- int source_length_;
- Handle<SeqAsciiString> seq_source_;
-
Isolate* isolate_;
- uc32 c0_;
+ Handle<StringType> source_;
+ // Used for external strings, to avoid going through the resource on
+ // every access.
+ const SourceChar* characters_;
+ int source_length_;
int position_;
+ uc32 c0_;
};
-template <bool seq_ascii>
-Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source) {
- isolate_ = source->map()->GetHeap()->isolate();
- FlattenString(source);
- source_ = source;
- source_length_ = source_->length();
-
- // Optimized fast case where we only have ASCII characters.
- if (seq_ascii) {
- seq_source_ = Handle<SeqAsciiString>::cast(source_);
- }
-
- // Set initial position right before the string.
- position_ = -1;
+template <typename StringType>
+Handle<Object> JsonParser<StringType>::ParseJson() {
+ // Initial position is right before the string.
+ ASSERT(position_ == -1);
// Advance to the first character (posibly EOS)
AdvanceSkipWhitespace();
+ // ParseJsonValue also consumes following whitespace.
Handle<Object> result = ParseJsonValue();
if (result.is_null() || c0_ != kEndOfString) {
// Parse failed. Current character is the unexpected token.
-
const char* message;
Factory* factory = isolate()->factory();
Handle<JSArray> array;
@@ -219,7 +231,7 @@ Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source) {
break;
}
- MessageLocation location(factory->NewScript(source),
+ MessageLocation location(factory->NewScript(source_),
position_,
position_ + 1);
Handle<Object> result = factory->NewSyntaxError(message, array);
@@ -231,8 +243,8 @@ Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source) {
// Parse any JSON value.
-template <bool seq_ascii>
-Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
+template <typename StringType>
+Handle<Object> JsonParser<StringType>::ParseJsonValue() {
switch (c0_) {
case '"':
return ParseJsonString();
@@ -283,13 +295,13 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
// Parse a JSON object. Position must be right at '{'.
-template <bool seq_ascii>
-Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
+template <typename StringType>
+Handle<Object> JsonParser<StringType>::ParseJsonObject() {
Handle<JSFunction> object_constructor(
isolate()->global_context()->object_function());
Handle<JSObject> json_object =
isolate()->factory()->NewJSObject(object_constructor);
- ASSERT_EQ(c0_, '{');
+ ASSERT_EQ('{', c0_);
AdvanceSkipWhitespace();
if (c0_ != '}') {
@@ -319,8 +331,8 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
}
// Parse a JSON array. Position must be right at '['.
-template <bool seq_ascii>
-Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
+template <typename StringType>
+Handle<Object> JsonParser<StringType>::ParseJsonArray() {
ZoneScope zone_scope(isolate(), DELETE_ON_EXIT);
ZoneList<Handle<Object> > elements(4);
ASSERT_EQ(c0_, '[');
@@ -347,8 +359,8 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
}
-template <bool seq_ascii>
-Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() {
+template <typename StringType>
+Handle<Object> JsonParser<StringType>::ParseJsonNumber() {
bool negative = false;
int beg_pos = position_;
if (c0_ == '-') {
@@ -391,24 +403,12 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() {
}
int length = position_ - beg_pos;
double number;
- if (seq_ascii) {
- Vector<const char> chars(seq_source_->GetChars() + beg_pos, length);
- number = StringToDouble(isolate()->unicode_cache(),
- chars,
- NO_FLAGS, // Hex, octal or trailing junk.
- OS::nan_value());
- } else {
- Vector<char> buffer = Vector<char>::New(length);
- String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
- Vector<const char> result =
- Vector<const char>(reinterpret_cast<const char*>(buffer.start()),
- length);
- number = StringToDouble(isolate()->unicode_cache(),
- result,
- NO_FLAGS, // Hex, octal or trailing junk.
- 0.0);
- buffer.Dispose();
- }
+
+ Vector<const SourceChar> chars(GetChars() + beg_pos, length);
+ number = StringToDouble(isolate()->unicode_cache(),
+ chars,
+ NO_FLAGS, // Hex, octal or trailing junk.
+ OS::nan_value());
SkipWhitespace();
return isolate()->factory()->NewNumber(number);
}
@@ -444,15 +444,17 @@ inline Handle<SeqAsciiString> NewRawString(Factory* factory, int length) {
// Scans the rest of a JSON string starting from position_ and writes
// prefix[start..end] along with the scanned characters into a
// sequential string of type StringType.
-template <bool seq_ascii>
-template <typename StringType, typename SinkChar>
-Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
+template <typename StringType>
+template <typename SinkStringType>
+Handle<String> JsonParser<StringType>::SlowScanJsonString(
Handle<String> prefix, int start, int end) {
+ typedef typename SinkStringType::CharType SinkChar;
int count = end - start;
int max_length = count + source_length_ - position_;
int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
- Handle<StringType> seq_str = NewRawString<StringType>(isolate()->factory(),
- length);
+ Handle<SinkStringType> seq_str =
+ NewRawString<SinkStringType>(isolate()->factory(),
+ length);
// Copy prefix into seq_str.
SinkChar* dest = seq_str->GetChars();
String::WriteToFlat(*prefix, dest, start, end);
@@ -462,7 +464,7 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
if (c0_ < 0x20) return Handle<String>::null();
if (count >= length) {
// We need to create a longer sequential string for the result.
- return SlowScanJsonString<StringType, SinkChar>(seq_str, 0, count);
+ return SlowScanJsonString<SinkStringType>(seq_str, 0, count);
}
if (c0_ != '\\') {
// If the sink can contain UC16 characters, or source_ contains only
@@ -470,16 +472,16 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
// character. Otherwise check whether the UC16 source character can fit
// in the ASCII sink.
if (sizeof(SinkChar) == kUC16Size ||
- seq_ascii ||
+ sizeof(SourceChar) == kCharSize ||
c0_ <= kMaxAsciiCharCode) {
SeqStringSet(seq_str, count++, c0_);
Advance();
} else {
- // StringType is SeqAsciiString and we just read a non-ASCII char.
- return SlowScanJsonString<SeqTwoByteString, uc16>(seq_str, 0, count);
+ // SinkStringType is SeqAsciiString and we just read a non-ASCII char.
+ return SlowScanJsonString<SeqTwoByteString>(seq_str, 0, count);
}
} else {
- Advance(); // Advance past the \.
+ Advance(); // Advance past the '\'.
switch (c0_) {
case '"':
case '\\':
@@ -518,9 +520,9 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
// StringType is SeqAsciiString and we just read a non-ASCII char.
position_ -= 6; // Rewind position_ to \ in \uxxxx.
Advance();
- return SlowScanJsonString<SeqTwoByteString, uc16>(seq_str,
- 0,
- count);
+ return SlowScanJsonString<SeqTwoByteString>(seq_str,
+ 0,
+ count);
}
}
default:
@@ -532,11 +534,11 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
// Shrink seq_string length to count.
if (isolate()->heap()->InNewSpace(*seq_str)) {
isolate()->heap()->new_space()->
- template ShrinkStringAtAllocationBoundary<StringType>(
+ template ShrinkStringAtAllocationBoundary<SinkStringType>(
*seq_str, count);
} else {
- int string_size = StringType::SizeFor(count);
- int allocated_string_size = StringType::SizeFor(length);
+ int string_size = SinkStringType::SizeFor(count);
+ int allocated_string_size = SinkStringType::SizeFor(length);
int delta = allocated_string_size - string_size;
Address start_filler_object = seq_str->address() + string_size;
seq_str->set_length(count);
@@ -549,9 +551,9 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
}
-template <bool seq_ascii>
+template <typename StringType>
template <bool is_symbol>
-Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
+Handle<String> JsonParser<StringType>::ScanJsonString() {
ASSERT_EQ('"', c0_);
Advance();
if (c0_ == '"') {
@@ -564,25 +566,24 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
// Check for control character (0x00-0x1f) or unterminated string (<0).
if (c0_ < 0x20) return Handle<String>::null();
if (c0_ != '\\') {
- if (seq_ascii || c0_ <= kMaxAsciiCharCode) {
+ if (c0_ <= kMaxAsciiCharCode) {
Advance();
} else {
- return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
- beg_pos,
- position_);
+ return SlowScanJsonString<SeqTwoByteString>(source_,
+ beg_pos,
+ position_);
}
} else {
- return SlowScanJsonString<SeqAsciiString, char>(source_,
- beg_pos,
- position_);
+ return SlowScanJsonString<SeqAsciiString>(source_,
+ beg_pos,
+ position_);
}
} while (c0_ != '"');
int length = position_ - beg_pos;
Handle<String> result;
- if (seq_ascii && is_symbol) {
- result = isolate()->factory()->LookupAsciiSymbol(seq_source_,
- beg_pos,
- length);
+ if (is_symbol && source_->IsSeqAsciiString()) {
+ result = isolate()->factory()->LookupAsciiSymbol(
+ Handle<SeqAsciiString>::cast(source_), beg_pos, length);
} else {
result = isolate()->factory()->NewRawAsciiString(length);
char* dest = SeqAsciiString::cast(*result)->GetChars();
@@ -594,6 +595,74 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
return result;
}
+
+template <typename StringType>
+void JsonParser<StringType>::InitializeSource() { }
+
+
+template <>
+void JsonParser<ExternalAsciiString>::InitializeSource() {
+ characters_ = source_->resource()->data();
+}
+
+
+template <>
+void JsonParser<ExternalTwoByteString>::InitializeSource() {
+ characters_ = source_->resource()->data();
+}
+
+
+template <>
+uc32 JsonParser<SeqAsciiString>::GetChar(int pos) {
+ return static_cast<uc32>(source_->SeqAsciiStringGet(pos));
+}
+
+
+template <>
+uc32 JsonParser<SeqTwoByteString>::GetChar(int pos) {
+ return static_cast<uc32>(source_->SeqTwoByteStringGet(pos));
+}
+
+
+template <>
+uc32 JsonParser<ExternalAsciiString>::GetChar(int pos) {
+ ASSERT(pos >= 0);
+ ASSERT(pos < source_length_);
+ return static_cast<uc32>(characters_[pos]);
+}
+
+
+template <>
+uc32 JsonParser<ExternalTwoByteString>::GetChar(int pos) {
+ ASSERT(pos >= 0);
+ ASSERT(pos < source_length_);
+ return static_cast<uc32>(characters_[pos]);
+}
+
+
+template <>
+const char* JsonParser<SeqAsciiString>::GetChars() {
+ return source_->GetChars();
+}
+
+
+template <>
+const uc16* JsonParser<SeqTwoByteString>::GetChars() {
+ return source_->GetChars();
+}
+
+
+template <>
+const char* JsonParser<ExternalAsciiString>::GetChars() {
+ return characters_;
+}
+
+
+template <>
+const uc16* JsonParser<ExternalTwoByteString>::GetChars() {
+ return characters_;
+}
+
} } // namespace v8::internal
#endif // V8_JSON_PARSER_H_
« no previous file with comments | « src/heap.cc ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698