Add CodeStubAssembler::FlattenString

R=danno@chromium.org
BUG=

Review-Url: https://chromiumcodereview.appspot.com/2435953002
Cr-Commit-Position: refs/heads/master@{#40456}
This commit is contained in:
jochen 2016-10-20 01:47:59 -07:00 committed by Commit bot
parent 5006df44c3
commit 9780e970ff
3 changed files with 81 additions and 0 deletions

View File

@ -3609,6 +3609,44 @@ Node* CodeStubAssembler::ToString(Node* context, Node* input) {
return result.value();
}
Node* CodeStubAssembler::FlattenString(Node* string) {
Variable var_result(this, MachineRepresentation::kTagged);
var_result.Bind(string);
Node* instance_type = LoadInstanceType(string);
// Check if the {string} is not a ConsString (i.e. already flat).
Label is_cons(this, Label::kDeferred), is_flat_in_cons(this), end(this);
{
GotoUnless(Word32Equal(Word32And(instance_type,
Int32Constant(kStringRepresentationMask)),
Int32Constant(kConsStringTag)),
&end);
// Check whether the right hand side is the empty string (i.e. if
// this is really a flat string in a cons string).
Node* rhs = LoadObjectField(string, ConsString::kSecondOffset);
Branch(WordEqual(rhs, EmptyStringConstant()), &is_flat_in_cons, &is_cons);
}
// Bail out to the runtime.
Bind(&is_cons);
{
var_result.Bind(
CallRuntime(Runtime::kFlattenString, NoContextConstant(), string));
Goto(&end);
}
Bind(&is_flat_in_cons);
{
var_result.Bind(LoadObjectField(string, ConsString::kFirstOffset));
Goto(&end);
}
Bind(&end);
return var_result.value();
}
Node* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) {
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
Label if_isreceiver(this, Label::kDeferred), if_isnotreceiver(this);

View File

@ -644,6 +644,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* JSReceiverToPrimitive(compiler::Node* context,
compiler::Node* input);
// Convert a String to a flat String.
compiler::Node* FlattenString(compiler::Node* string);
enum ToIntegerTruncationMode {
kNoTruncation,
kTruncateMinusZero,

View File

@ -175,6 +175,46 @@ TEST(ToString) {
}
}
TEST(FlattenString) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1;
CodeStubAssemblerTester m(isolate, kNumParams);
m.Return(m.FlattenString(m.Parameter(0)));
Handle<Code> code = m.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<FixedArray> test_cases(isolate->factory()->NewFixedArray(4));
Handle<String> expected(
isolate->factory()->InternalizeUtf8String("hello, world!"));
test_cases->set(0, *expected);
Handle<String> string(
isolate->factory()->InternalizeUtf8String("filler hello, world! filler"));
Handle<String> sub_string(
isolate->factory()->NewProperSubString(string, 7, 20));
test_cases->set(1, *sub_string);
Handle<String> hello(isolate->factory()->InternalizeUtf8String("hello,"));
Handle<String> world(isolate->factory()->InternalizeUtf8String(" world!"));
Handle<String> cons_str(
isolate->factory()->NewConsString(hello, world).ToHandleChecked());
test_cases->set(2, *cons_str);
Handle<String> empty(isolate->factory()->InternalizeUtf8String(""));
Handle<String> fake_cons_str(
isolate->factory()->NewConsString(expected, empty).ToHandleChecked());
test_cases->set(3, *fake_cons_str);
for (int i = 0; i < 4; ++i) {
Handle<String> test = handle(String::cast(test_cases->get(i)));
Handle<Object> result = ft.Call(test).ToHandleChecked();
CHECK(result->IsString());
CHECK(Handle<String>::cast(result)->IsFlat());
CHECK(String::Equals(Handle<String>::cast(result), expected));
}
}
TEST(TryToName) {
typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable;