Commit e68258bd authored by bakkot's avatar bakkot Committed by Commit bot

[AST] Add method to concatenate AstRawStrings

Normally the parser just uses AstConsStrings to concatenate, but some
types require an AstRawString. This patch adds an AstValueFactory
method which produces one from two AstRawStrings.

Review-Url: https://codereview.chromium.org/2348783002
Cr-Commit-Position: refs/heads/master@{#39482}
parent aa6db9d9
......@@ -274,6 +274,38 @@ const AstConsString* AstValueFactory::NewConsString(
return new_string;
}
const AstRawString* AstValueFactory::ConcatStrings(const AstRawString* left,
const AstRawString* right) {
int left_length = left->length();
int right_length = right->length();
const unsigned char* left_data = left->raw_data();
const unsigned char* right_data = right->raw_data();
if (left->is_one_byte() && right->is_one_byte()) {
uint8_t* buffer = zone_->NewArray<uint8_t>(left_length + right_length);
memcpy(buffer, left_data, left_length);
memcpy(buffer + left_length, right_data, right_length);
Vector<const uint8_t> literal(buffer, left_length + right_length);
return GetOneByteStringInternal(literal);
} else {
uint16_t* buffer = zone_->NewArray<uint16_t>(left_length + right_length);
if (left->is_one_byte()) {
for (int i = 0; i < left_length; ++i) {
buffer[i] = left_data[i];
}
} else {
memcpy(buffer, left_data, 2 * left_length);
}
if (right->is_one_byte()) {
for (int i = 0; i < right_length; ++i) {
buffer[i + left_length] = right_data[i];
}
} else {
memcpy(buffer + left_length, right_data, 2 * right_length);
}
Vector<const uint16_t> literal(buffer, left_length + right_length);
return GetTwoByteStringInternal(literal);
}
}
void AstValueFactory::Internalize(Isolate* isolate) {
if (isolate_) {
......
......@@ -355,6 +355,8 @@ class AstValueFactory {
const AstRawString* GetString(Handle<String> literal);
const AstConsString* NewConsString(const AstString* left,
const AstString* right);
const AstRawString* ConcatStrings(const AstRawString* left,
const AstRawString* right);
void Internalize(Isolate* isolate);
bool IsInternalized() {
......
......@@ -58,3 +58,43 @@ TEST(List) {
CHECK_EQ(0, list->length());
delete list;
}
TEST(ConcatStrings) {
v8::base::AccountingAllocator allocator;
Zone zone(&allocator);
AstValueFactory value_factory(&zone, 0);
const AstRawString* one_byte = value_factory.GetOneByteString("a");
uint16_t two_byte_buffer[] = {
0x3b1,
};
const AstRawString* two_byte = value_factory.GetTwoByteString(
Vector<const uint16_t>(two_byte_buffer, 1));
const AstRawString* expectation = value_factory.GetOneByteString("aa");
const AstRawString* result = value_factory.ConcatStrings(one_byte, one_byte);
CHECK(result->is_one_byte());
CHECK_EQ(expectation, result);
uint16_t expectation_buffer_one_two[] = {'a', 0x3b1};
expectation = value_factory.GetTwoByteString(
Vector<const uint16_t>(expectation_buffer_one_two, 2));
result = value_factory.ConcatStrings(one_byte, two_byte);
CHECK(!result->is_one_byte());
CHECK_EQ(expectation, result);
uint16_t expectation_buffer_two_one[] = {0x3b1, 'a'};
expectation = value_factory.GetTwoByteString(
Vector<const uint16_t>(expectation_buffer_two_one, 2));
result = value_factory.ConcatStrings(two_byte, one_byte);
CHECK(!result->is_one_byte());
CHECK_EQ(expectation, result);
uint16_t expectation_buffer_two_two[] = {0x3b1, 0x3b1};
expectation = value_factory.GetTwoByteString(
Vector<const uint16_t>(expectation_buffer_two_two, 2));
result = value_factory.ConcatStrings(two_byte, two_byte);
CHECK(!result->is_one_byte());
CHECK_EQ(expectation, result);
}
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