Reviewers: dcarney,
Message:
This is a follow-up to http://codereview.chromium.org/10918169/
I changed the encoding to use an enum instead of constants.
I also changed the signature of GetExternalStringResourceBase to return the
resource base as return value and return the encoding as call-by-reference
variable. The semantic changed slightly: if the string is not an external
string, the encoding is returned nevertheless (bit masking should be just as
cheap as assigning 0 to the return value).
Description:
Introduce new API to expose external string resource regardless of encoding.
BUG=
Please review this at http://codereview.chromium.org/10917211/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M include/v8.h
M src/api.cc
M src/objects-inl.h
M test/cctest/test-api.cc
Index: include/v8.h
diff --git a/include/v8.h b/include/v8.h
index
ddde388cd4f27c970c29e351333b06cd94b5c026..37d66586aa08f0aea782f8152bc9639e4bef4de8
100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1018,6 +1018,11 @@ class Boolean : public Primitive {
*/
class String : public Primitive {
public:
+ enum Encoding {
+ UNKNOWN_ENCODING = 0x1,
+ TWO_BYTE_ENCODING = 0x0,
+ ASCII_ENCODING = 0x4
+ };
/**
* Returns the number of characters in this string.
*/
@@ -1181,6 +1186,14 @@ class String : public Primitive {
};
/**
+ * If the string is an external string, return the
ExternalStringResourceBase
+ * regardless of the encoding, otherwise return NULL. The encoding of
the
+ * string is returned in type_out.
+ */
+ inline ExternalStringResourceBase* GetExternalStringResourceBase(
+ Encoding* encoding_out) const;
+
+ /**
* Get the ExternalStringResource for an external string. Returns
* NULL if IsExternal() doesn't return true.
*/
@@ -1226,6 +1239,8 @@ class String : public Primitive {
* this function should not otherwise delete or modify the resource.
Neither
* should the underlying buffer be deallocated or modified except
through the
* destructor of the external string resource.
+ * The optional encoding argument provides a hint on whether scanning for
+ * ASCII content is necessary.
*/
V8EXPORT static Local<String> NewExternal(ExternalStringResource*
resource);
@@ -1343,6 +1358,8 @@ class String : public Primitive {
};
private:
+ V8EXPORT void
VerifyExternalStringResourceBase(ExternalStringResourceBase* v,
+ Encoding encoding_out)
const;
V8EXPORT void VerifyExternalStringResource(ExternalStringResource* val)
const;
V8EXPORT static void CheckCast(v8::Value* obj);
};
@@ -4033,7 +4050,9 @@ class Internals {
static const int kForeignAddressOffset = kApiPointerSize;
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
static const int kFullStringRepresentationMask = 0x07;
+ static const int kStringEncodingMask = 0x4;
static const int kExternalTwoByteRepresentationTag = 0x02;
+ static const int kExternalAsciiRepresentationTag = 0x06;
static const int kIsolateStateOffset = 0;
static const int kIsolateEmbedderDataOffset = 1 * kApiPointerSize;
@@ -4388,6 +4407,26 @@ String::ExternalStringResource*
String::GetExternalStringResource() const {
}
+String::ExternalStringResourceBase* String::GetExternalStringResourceBase(
+ String::Encoding* encoding_out) const {
+ typedef internal::Object O;
+ typedef internal::Internals I;
+ O* obj = *reinterpret_cast<O**>(const_cast<String*>(this));
+ int type = I::GetInstanceType(obj) & I::kFullStringRepresentationMask;
+ *encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
+ ExternalStringResourceBase* resource = NULL;
+ if (type == I::kExternalAsciiRepresentationTag ||
+ type == I::kExternalTwoByteRepresentationTag) {
+ void* value = I::ReadField<void*>(obj, I::kStringResourceOffset);
+ resource = static_cast<ExternalStringResourceBase*>(value);
+ }
+#ifdef V8_ENABLE_CHECKS
+ VerifyExternalStringResourceBase(resource, *encoding_out);
+#endif
+ return resource;
+}
+
+
bool Value::IsUndefined() const {
#ifdef V8_ENABLE_CHECKS
return FullIsUndefined();
Index: src/api.cc
diff --git a/src/api.cc b/src/api.cc
index
5c76e32a1b4ec24734b2279c29c1ab8f0f1a428e..9dd6dae8d135f186b4cb1b9645b163c76159c90b
100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -4089,6 +4089,30 @@ void v8::String::VerifyExternalStringResource(
CHECK_EQ(expected, value);
}
+void v8::String::VerifyExternalStringResourceBase(
+ v8::String::ExternalStringResourceBase* value,
+ Encoding encoding) const {
+ i::Handle<i::String> str = Utils::OpenHandle(this);
+ const v8::String::ExternalStringResourceBase* expected;
+ Encoding expectedEncoding;
+ if (i::StringShape(*str).IsExternalAscii()) {
+ const void* resource =
+ i::Handle<i::ExternalAsciiString>::cast(str)->resource();
+ expected = reinterpret_cast<const
ExternalStringResourceBase*>(resource);
+ expectedEncoding = ASCII_ENCODING;
+ } else if (i::StringShape(*str).IsExternalTwoByte()) {
+ const void* resource =
+ i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
+ expected = reinterpret_cast<const
ExternalStringResourceBase*>(resource);
+ expectedEncoding = TWO_BYTE_ENCODING;
+ } else {
+ expected = NULL;
+ expectedEncoding = str->IsAsciiRepresentation() ? ASCII_ENCODING
+ : TWO_BYTE_ENCODING;
+ }
+ CHECK_EQ(expected, value);
+ CHECK_EQ(expectedEncoding, encoding);
+}
const v8::String::ExternalAsciiStringResource*
v8::String::GetExternalAsciiStringResource() const {
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index
3b9bb0a13783fd6829bbffe3a678b6babeeb08c4..391358386d5102d26f22c236e4fe81a061698378
100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -382,6 +382,9 @@ uint32_t StringShape::full_representation_tag() {
STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
Internals::kFullStringRepresentationMask);
+STATIC_CHECK(static_cast<uint32_t>(kStringEncodingMask) ==
+ Internals::kStringEncodingMask);
+
bool StringShape::IsSequentialAscii() {
return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
@@ -398,6 +401,12 @@ bool StringShape::IsExternalAscii() {
}
+STATIC_CHECK((kExternalStringTag | kAsciiStringTag) ==
+ Internals::kExternalAsciiRepresentationTag);
+
+STATIC_CHECK(v8::String::ASCII_ENCODING == kAsciiStringTag);
+
+
bool StringShape::IsExternalTwoByte() {
return full_representation_tag() == (kExternalStringTag |
kTwoByteStringTag);
}
@@ -406,6 +415,7 @@ bool StringShape::IsExternalTwoByte() {
STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
Internals::kExternalTwoByteRepresentationTag);
+STATIC_CHECK(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
uc32 FlatStringReader::Get(int index) {
ASSERT(0 <= index && index <= length_);
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index
4bd99a6d9e940abd97ba243ecb383a119f4854f3..09125e1407c1ae84921005737437dc74f79ddf0d
100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -404,6 +404,10 @@ THREADED_TEST(ScriptUsingStringResource) {
CHECK(source->IsExternal());
CHECK_EQ(resource,
static_cast<TestResource*>(source->GetExternalStringResource()));
+ String::Encoding encoding = String::UNKNOWN_ENCODING;
+ CHECK_EQ(static_cast<const
String::ExternalStringResourceBase*>(resource),
+ source->GetExternalStringResourceBase(&encoding));
+ CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
CHECK_EQ(0, dispose_count);
}
@@ -419,9 +423,16 @@ THREADED_TEST(ScriptUsingAsciiStringResource) {
{
v8::HandleScope scope;
LocalContext env;
- Local<String> source =
- String::NewExternal(new TestAsciiResource(i::StrDup(c_source),
- &dispose_count));
+ TestAsciiResource* resource = new
TestAsciiResource(i::StrDup(c_source),
+ &dispose_count);
+ Local<String> source = String::NewExternal(resource);
+ CHECK(source->IsExternalAscii());
+ CHECK_EQ(static_cast<const
String::ExternalStringResourceBase*>(resource),
+ source->GetExternalAsciiStringResource());
+ String::Encoding encoding = String::UNKNOWN_ENCODING;
+ CHECK_EQ(static_cast<const
String::ExternalStringResourceBase*>(resource),
+ source->GetExternalStringResourceBase(&encoding));
+ CHECK_EQ(String::ASCII_ENCODING, encoding);
Local<Script> script = Script::Compile(source);
Local<Value> value = script->Run();
CHECK(value->IsNumber());
@@ -445,6 +456,11 @@ THREADED_TEST(ScriptMakingExternalString) {
// Trigger GCs so that the newly allocated string moves to old gen.
HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
+ CHECK_EQ(source->IsExternal(), false);
+ CHECK_EQ(source->IsExternalAscii(), false);
+ String::Encoding encoding = String::UNKNOWN_ENCODING;
+ CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
+ CHECK_EQ(String::ASCII_ENCODING, encoding);
bool success = source->MakeExternal(new TestResource(two_byte_source,
&dispose_count));
CHECK(success);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev