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

Unified Diff: src/builtins/builtins-string.cc

Issue 2358263002: [builtins] migrate C++ String Iterator builtins to baseline TurboFan (Closed)
Patch Set: v3 (try again, but probably not ._.) Created 4 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
Index: src/builtins/builtins-string.cc
diff --git a/src/builtins/builtins-string.cc b/src/builtins/builtins-string.cc
index 640e425d23e47b6678af913a5da40d04ab055dc5..7ca6a5aca93311a05d0c7abe585b5da5ec929d00 100644
--- a/src/builtins/builtins-string.cc
+++ b/src/builtins/builtins-string.cc
@@ -616,58 +616,189 @@ void Builtins::Generate_StringPrototypeValueOf(CodeStubAssembler* assembler) {
assembler->Return(result);
}
-BUILTIN(StringPrototypeIterator) {
- HandleScope scope(isolate);
- TO_THIS_STRING(object, "String.prototype[Symbol.iterator]");
+void Builtins::Generate_StringPrototypeIterator(CodeStubAssembler* assembler) {
+ typedef CodeStubAssembler::Label Label;
+ typedef compiler::Node Node;
+ typedef CodeStubAssembler::Variable Variable;
- Handle<String> string;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
- Object::ToString(isolate, object));
+ Variable var_string(assembler, MachineRepresentation::kTagged);
+ Variable var_index(assembler, MachineRepresentation::kWord32);
- return *isolate->factory()->NewJSStringIterator(string);
-}
+ Variable* loop_inputs[] = {&var_string, &var_index};
+ Label loop(assembler, 2, loop_inputs);
+ Label allocate_iterator(assembler);
-BUILTIN(StringIteratorPrototypeNext) {
- HandleScope scope(isolate);
+ Node* receiver = assembler->Parameter(0);
+ Node* context = assembler->Parameter(3);
- if (!args.receiver()->IsJSStringIterator()) {
- Handle<String> reason = isolate->factory()->NewStringFromAsciiChecked(
- "String Iterator.prototype.next");
- THROW_NEW_ERROR_RETURN_FAILURE(
- isolate,
- NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, reason));
- }
- Handle<JSStringIterator> iterator =
- Handle<JSStringIterator>::cast(args.receiver());
- Handle<String> string(iterator->string());
-
- int position = iterator->index();
- int length = string->length();
-
- if (position < length) {
- uint16_t lead = string->Get(position);
- if (lead >= 0xD800 && lead <= 0xDBFF && position + 1 < length) {
- uint16_t trail = string->Get(position + 1);
- if (V8_LIKELY(trail >= 0xDC00 && trail <= 0xDFFF)) {
- // Return surrogate pair code units
- iterator->set_index(position + 2);
- Handle<String> value =
- isolate->factory()->NewSurrogatePairString(lead, trail);
- return *isolate->factory()->NewJSIteratorResult(value, false);
+ Node* string =
+ assembler->ToThisValue(context, receiver, PrimitiveType::kString,
+ "String.prototype[Symbol.iterator]");
+ var_string.Bind(string);
+ var_index.Bind(assembler->Int32Constant(0));
+
+ assembler->Goto(&loop);
+ assembler->Bind(&loop);
+ {
+ // Load the instance type of the {string}.
+ Node* string_instance_type = assembler->LoadInstanceType(string);
+
+ // Check if the {string} is a SeqString.
+ Label if_stringisnotsequential(assembler);
+ assembler->Branch(assembler->Word32Equal(
+ assembler->Word32And(string_instance_type,
+ assembler->Int32Constant(
+ kStringRepresentationMask)),
+ assembler->Int32Constant(kSeqStringTag)),
+ &allocate_iterator, &if_stringisnotsequential);
+
+ assembler->Bind(&if_stringisnotsequential);
+ {
+ // Check if the {string} is a ConsString.
+ Label if_stringiscons(assembler), if_stringisnotcons(assembler);
+ assembler->Branch(
+ assembler->Word32Equal(
+ assembler->Word32And(
+ string_instance_type,
+ assembler->Int32Constant(kStringRepresentationMask)),
+ assembler->Int32Constant(kConsStringTag)),
+ &if_stringiscons, &if_stringisnotcons);
+
+ assembler->Bind(&if_stringiscons);
+ {
+ // Flatten cons-string and finish.
+ var_string.Bind(assembler->CallRuntime(
+ Runtime::kFlattenString, assembler->NoContextConstant(), string));
+ assembler->Goto(&allocate_iterator);
+ }
+
+ assembler->Bind(&if_stringisnotcons);
+ {
+ // Check if the {string} is an ExternalString.
+ Label if_stringisnotexternal(assembler);
+ assembler->Branch(
+ assembler->Word32Equal(
+ assembler->Word32And(
+ string_instance_type,
+ assembler->Int32Constant(kStringRepresentationMask)),
+ assembler->Int32Constant(kExternalStringTag)),
+ &allocate_iterator, &if_stringisnotexternal);
+
+ assembler->Bind(&if_stringisnotexternal);
+ {
+ // The {string} is a SlicedString, continue with its parent.
+ Node* index = var_index.value();
+ Node* string_offset = assembler->LoadAndUntagObjectField(
+ string, SlicedString::kOffsetOffset);
+ Node* string_parent =
+ assembler->LoadObjectField(string, SlicedString::kParentOffset);
+ var_index.Bind(assembler->IntPtrAdd(index, string_offset));
+ var_string.Bind(string_parent);
+ assembler->Goto(&loop);
+ }
}
}
+ }
- // Return single code unit
- iterator->set_index(position + 1);
- Handle<String> value =
- isolate->factory()->LookupSingleCharacterStringFromCode(lead);
- return *isolate->factory()->NewJSIteratorResult(value, false);
+ assembler->Bind(&allocate_iterator);
+ {
+ Node* native_context = assembler->LoadNativeContext(context);
+ Node* index = assembler->Int32Constant(Context::STRING_ITERATOR_MAP_INDEX);
+ Node* map = assembler->LoadFixedArrayElement(
+ native_context, index, 0, CodeStubAssembler::INTPTR_PARAMETERS);
+ Node* js_iter = assembler->Allocate(JSStringIterator::kSize);
+ assembler->StoreMapNoWriteBarrier(js_iter, map);
+ assembler->StoreObjectFieldRoot(js_iter, JSValue::kPropertiesOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldRoot(js_iter, JSObject::kElementsOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectField(js_iter, JSStringIterator::kStringOffset,
+ var_string.value());
+
+ assembler->StoreObjectField(js_iter, JSStringIterator::kNextIndexOffset,
+ assembler->SmiFromWord32(var_index.value()));
+ assembler->Return(js_iter);
+ }
+}
+
+void Builtins::Generate_StringIteratorPrototypeNext(
+ CodeStubAssembler* assembler) {
+ typedef CodeStubAssembler::Label Label;
+ typedef compiler::Node Node;
+ typedef CodeStubAssembler::Variable Variable;
+
+ Variable var_value(assembler, MachineRepresentation::kTagged);
+ Variable var_done(assembler, MachineRepresentation::kTagged);
+
+ var_value.Bind(assembler->UndefinedConstant());
+ var_done.Bind(assembler->BooleanConstant(true));
+
+ Label throw_bad_receiver(assembler), next_codepoint(assembler),
+ return_result(assembler);
+
+ Node* js_iter = assembler->Parameter(0);
Benedikt Meurer 2016/09/22 03:48:23 Nit: rename js_iter to iterator.
+ Node* context = assembler->Parameter(3);
+
+ assembler->GotoIf(assembler->WordIsSmi(js_iter), &throw_bad_receiver);
+ assembler->GotoUnless(
+ assembler->WordEqual(assembler->LoadInstanceType(js_iter),
+ assembler->Int32Constant(JS_STRING_ITERATOR_TYPE)),
+ &throw_bad_receiver);
+
+ Node* string =
+ assembler->LoadObjectField(js_iter, JSStringIterator::kStringOffset);
+ Node* position = assembler->LoadAndUntagObjectField(
+ js_iter, JSStringIterator::kNextIndexOffset);
+ Node* length =
+ assembler->LoadAndUntagObjectField(string, String::kLengthOffset);
+
+ assembler->Branch(assembler->Int32LessThan(position, length), &next_codepoint,
+ &return_result);
+
+ assembler->Bind(&next_codepoint);
+ {
+ Node* value = assembler->StringFromCodePointAt(string, length, position);
+ Node* length =
+ assembler->LoadAndUntagObjectField(value, String::kLengthOffset);
+ assembler->StoreObjectFieldNoWriteBarrier(
+ js_iter, JSStringIterator::kNextIndexOffset,
+ assembler->SmiFromWord32(assembler->Int32Add(position, length)));
+ var_value.Bind(value);
+ var_done.Bind(assembler->BooleanConstant(false));
+ assembler->Goto(&return_result);
}
- iterator->set_string(isolate->heap()->empty_string());
+ assembler->Bind(&return_result);
+ {
+ Node* native_context = assembler->LoadNativeContext(context);
+ Node* map = assembler->LoadFixedArrayElement(
+ native_context,
+ assembler->Int32Constant(Context::ITERATOR_RESULT_MAP_INDEX), 0,
Benedikt Meurer 2016/09/22 03:48:23 This must be IntPtrConstant then.
+ CodeStubAssembler::INTPTR_PARAMETERS);
+ Node* iterator = assembler->Allocate(JSIteratorResult::kSize);
Benedikt Meurer 2016/09/22 03:48:22 Nit: Rename iterator to result.
+ assembler->StoreMapNoWriteBarrier(iterator, map);
+ assembler->StoreObjectFieldRoot(iterator,
+ JSIteratorResult::kPropertiesOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldRoot(iterator, JSIteratorResult::kElementsOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectField(iterator, JSIteratorResult::kValueOffset,
+ var_value.value());
+ assembler->StoreObjectField(iterator, JSIteratorResult::kDoneOffset,
+ var_done.value());
+ assembler->Return(iterator);
+ }
- return *isolate->factory()->NewJSIteratorResult(
- isolate->factory()->undefined_value(), true);
+ assembler->Bind(&throw_bad_receiver);
+ {
+ // The {receiver} is not a valid JSGeneratorObject.
+ Node* result = assembler->CallRuntime(
+ Runtime::kThrowIncompatibleMethodReceiver, context,
+ assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
+ "String Iterator.prototype.next", TENURED)),
+ js_iter);
+ assembler->Return(result); // Never reached.
+ }
}
} // namespace internal
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | src/code-stub-assembler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698