Commit 6a9e4048 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Introduce new API to expose external string resource regardless of encoding.

BUG=

Review URL: https://chromiumcodereview.appspot.com/10917211

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12488 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7276fa39
......@@ -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.
*/
......@@ -1180,6 +1185,14 @@ class String : public Primitive {
ExternalAsciiStringResource() {}
};
/**
* 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 encoding_out.
*/
inline ExternalStringResourceBase* GetExternalStringResourceBase(
Encoding* encoding_out) const;
/**
* Get the ExternalStringResource for an external string. Returns
* NULL if IsExternal() doesn't return true.
......@@ -1343,6 +1356,8 @@ class String : public Primitive {
};
private:
V8EXPORT void VerifyExternalStringResourceBase(ExternalStringResourceBase* v,
Encoding encoding) const;
V8EXPORT void VerifyExternalStringResource(ExternalStringResource* val) const;
V8EXPORT static void CheckCast(v8::Value* obj);
};
......@@ -4033,7 +4048,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 +4405,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();
......
......@@ -4089,6 +4089,29 @@ 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 {
......
......@@ -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_);
......
......@@ -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);
......
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