Commit 53e00e39 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

Reland "[turbofan] Move String.* functions to JSCallReducer"

This is a reland of 3ff4b447.

Original version did not handle V8_INTL_SUPPORT.

Original change's description:
> [turbofan] Move String.* functions to JSCallReducer
>
> Bug: v8:7250, v8:7340
> Change-Id: Ibb8d5badf89c66bd9bcb6bb390256ae81d0e899c
> Reviewed-on: https://chromium-review.googlesource.com/913208
> Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#51505}

Bug: v8:7250, v8:7340
Change-Id: Id908cbcfaa9e9cf5459d6d3289e6ec00e387d287
Reviewed-on: https://chromium-review.googlesource.com/934268Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51514}
parent 481c21e0
This diff is collapsed.
......@@ -75,13 +75,8 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final
Reduction ReduceNumberIsSafeInteger(Node* node);
Reduction ReduceNumberParseInt(Node* node);
Reduction ReduceObjectCreate(Node* node);
Reduction ReduceStringConcat(Node* node);
Reduction ReduceStringFromCharCode(Node* node);
Reduction ReduceStringIterator(Node* node);
Reduction ReduceStringIteratorNext(Node* node);
Reduction ReduceStringSlice(Node* node);
Reduction ReduceStringToLowerCaseIntl(Node* node);
Reduction ReduceStringToUpperCaseIntl(Node* node);
Reduction ReduceStringConcat(Node* node);
Reduction ReduceArrayBufferIsView(Node* node);
Reduction ReduceArrayBufferViewAccessor(Node* node,
InstanceType instance_type,
......
This diff is collapsed.
......@@ -100,6 +100,16 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
Reduction ReduceStringPrototypeIndexOf(Node* node);
Reduction ReduceStringPrototypeStringAt(
const Operator* string_access_operator, Node* node);
#ifdef V8_INTL_SUPPORT
Reduction ReduceStringPrototypeToLowerCaseIntl(Node* node);
Reduction ReduceStringPrototypeToUpperCaseIntl(Node* node);
#endif // V8_INTL_SUPPORT
Reduction ReduceStringFromCharCode(Node* node);
Reduction ReduceStringPrototypeIterator(Node* node);
Reduction ReduceStringIteratorPrototypeNext(Node* node);
Reduction ReduceAsyncFunctionPromiseCreate(Node* node);
Reduction ReduceAsyncFunctionPromiseRelease(Node* node);
Reduction ReducePromiseCapabilityDefaultReject(Node* node);
......
......@@ -143,6 +143,8 @@ Reduction JSCreateLowering::Reduce(Node* node) {
return ReduceJSCreateClosure(node);
case IrOpcode::kJSCreateIterResultObject:
return ReduceJSCreateIterResultObject(node);
case IrOpcode::kJSCreateStringIterator:
return ReduceJSCreateStringIterator(node);
case IrOpcode::kJSCreateKeyValueArray:
return ReduceJSCreateKeyValueArray(node);
case IrOpcode::kJSCreatePromise:
......@@ -982,6 +984,28 @@ Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
return Changed(node);
}
Reduction JSCreateLowering::ReduceJSCreateStringIterator(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateStringIterator, node->opcode());
Node* string = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node);
Node* map = jsgraph()->HeapConstant(
handle(native_context()->string_iterator_map(), isolate()));
// Allocate new iterator and attach the iterator to this string.
AllocationBuilder a(jsgraph(), effect, graph()->start());
a.Allocate(JSStringIterator::kSize, NOT_TENURED, Type::OtherObject());
a.Store(AccessBuilder::ForMap(), map);
a.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
jsgraph()->EmptyFixedArrayConstant());
a.Store(AccessBuilder::ForJSObjectElements(),
jsgraph()->EmptyFixedArrayConstant());
a.Store(AccessBuilder::ForJSStringIteratorString(), string);
a.Store(AccessBuilder::ForJSStringIteratorIndex(), jsgraph()->SmiConstant(0));
STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
a.FinishAndChange(node);
return Changed(node);
}
Reduction JSCreateLowering::ReduceJSCreateKeyValueArray(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateKeyValueArray, node->opcode());
Node* key = NodeProperties::GetValueInput(node, 0);
......
......@@ -53,6 +53,7 @@ class V8_EXPORT_PRIVATE JSCreateLowering final
Reduction ReduceJSCreateBoundFunction(Node* node);
Reduction ReduceJSCreateClosure(Node* node);
Reduction ReduceJSCreateIterResultObject(Node* node);
Reduction ReduceJSCreateStringIterator(Node* node);
Reduction ReduceJSCreateKeyValueArray(Node* node);
Reduction ReduceJSCreatePromise(Node* node);
Reduction ReduceJSCreateLiteralArrayOrObject(Node* node);
......
......@@ -418,6 +418,10 @@ void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
}
void JSGenericLowering::LowerJSCreateStringIterator(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
}
void JSGenericLowering::LowerJSCreateKeyValueArray(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
}
......
......@@ -569,6 +569,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
V(ToString, Operator::kNoProperties, 1, 1) \
V(Create, Operator::kNoProperties, 2, 1) \
V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \
V(CreateStringIterator, Operator::kEliminatable, 1, 1) \
V(CreateKeyValueArray, Operator::kEliminatable, 2, 1) \
V(CreatePromise, Operator::kEliminatable, 0, 1) \
V(HasProperty, Operator::kNoProperties, 2, 1) \
......
......@@ -658,6 +658,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
Handle<FeedbackCell> feedback_cell,
PretenureFlag pretenure = NOT_TENURED);
const Operator* CreateIterResultObject();
const Operator* CreateStringIterator();
const Operator* CreateKeyValueArray();
const Operator* CreatePromise();
const Operator* CreateLiteralArray(Handle<ConstantElementsPair> constant,
......
......@@ -515,6 +515,27 @@ MaybeHandle<Map> NodeProperties::GetMapWitness(Node* node) {
return MaybeHandle<Map>();
}
// static
bool NodeProperties::HasInstanceTypeWitness(Node* receiver, Node* effect,
InstanceType instance_type) {
ZoneHandleSet<Map> receiver_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps);
switch (result) {
case NodeProperties::kUnreliableReceiverMaps:
case NodeProperties::kReliableReceiverMaps:
DCHECK_NE(0, receiver_maps.size());
for (size_t i = 0; i < receiver_maps.size(); ++i) {
if (receiver_maps[i]->instance_type() != instance_type) return false;
}
return true;
case NodeProperties::kNoReceiverMaps:
return false;
}
UNREACHABLE();
}
// static
bool NodeProperties::NoObservableSideEffectBetween(Node* effect,
Node* dominator) {
......
......@@ -155,6 +155,8 @@ class V8_EXPORT_PRIVATE NodeProperties final {
Node* receiver, Node* effect, ZoneHandleSet<Map>* maps_return);
static MaybeHandle<Map> GetMapWitness(Node* node);
static bool HasInstanceTypeWitness(Node* receiver, Node* effect,
InstanceType instance_type);
// Walks up the {effect} chain to check that there's no observable side-effect
// between the {effect} and it's {dominator}. Aborts the walk if there's join
......
......@@ -140,6 +140,7 @@
V(JSCreateClosure) \
V(JSCreateGeneratorObject) \
V(JSCreateIterResultObject) \
V(JSCreateStringIterator) \
V(JSCreateKeyValueArray) \
V(JSCreatePromise) \
V(JSCreateLiteralArray) \
......
......@@ -1225,6 +1225,10 @@ Type* Typer::Visitor::TypeJSCreateIterResultObject(Node* node) {
return Type::OtherObject();
}
Type* Typer::Visitor::TypeJSCreateStringIterator(Node* node) {
return Type::OtherObject();
}
Type* Typer::Visitor::TypeJSCreateKeyValueArray(Node* node) {
return Type::OtherObject();
}
......@@ -1958,9 +1962,13 @@ Type* Typer::Visitor::StringFromCodePointTyper(Type* type, Typer* t) {
Type* Typer::Visitor::TypeStringCharAt(Node* node) { return Type::String(); }
Type* Typer::Visitor::TypeStringToLowerCaseIntl(Node* node) { UNREACHABLE(); }
Type* Typer::Visitor::TypeStringToLowerCaseIntl(Node* node) {
return Type::String();
}
Type* Typer::Visitor::TypeStringToUpperCaseIntl(Node* node) { UNREACHABLE(); }
Type* Typer::Visitor::TypeStringToUpperCaseIntl(Node* node) {
return Type::String();
}
Type* Typer::Visitor::TypeStringCharCodeAt(Node* node) {
return typer_->cache_.kUint16;
......
......@@ -677,6 +677,10 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
// Type is OtherObject.
CheckTypeIs(node, Type::OtherObject());
break;
case IrOpcode::kJSCreateStringIterator:
// Type is OtherObject.
CheckTypeIs(node, Type::OtherObject());
break;
case IrOpcode::kJSCreateKeyValueArray:
// Type is OtherObject.
CheckTypeIs(node, Type::OtherObject());
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file.
// Flags: --allow-natives-syntax --opt --no-always-opt
(()=> {
function f(a, b, c) {
return a.indexOf(b, c);
}
f("abc", "de", 1);
f("abc", "de", 1);
%OptimizeFunctionOnNextCall(f);
f("abc", "de", {});
%OptimizeFunctionOnNextCall(f);
f("abc", "de", {});
assertOptimized(f);
})();
(()=> {
function f(a, b, c) {
return a.indexOf(b, c);
}
f("abc", "de", 1);
f("abc", "de", 1);
%OptimizeFunctionOnNextCall(f);
f("abc", {}, 1);
%OptimizeFunctionOnNextCall(f);
f("abc", {}, 1);
assertOptimized(f);
})();
......@@ -328,46 +328,6 @@ TEST_F(JSBuiltinReducerTest, NumberParseIntWithIntegral32AndUndefined) {
}
}
// -----------------------------------------------------------------------------
// String.fromCharCode
TEST_F(JSBuiltinReducerTest, StringFromCharCodeWithNumber) {
Node* function = StringFunction("fromCharCode");
Node* effect = graph()->start();
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0);
Node* call =
graph()->NewNode(javascript()->Call(3), function, UndefinedConstant(),
p0, context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsStringFromCharCode(p0));
}
}
TEST_F(JSBuiltinReducerTest, StringFromCharCodeWithPlainPrimitive) {
Node* function = StringFunction("fromCharCode");
Node* effect = graph()->start();
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
Node* call =
graph()->NewNode(javascript()->Call(3), function, UndefinedConstant(), p0,
context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsStringFromCharCode(IsPlainPrimitiveToNumber(p0)));
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -67,6 +67,19 @@ class JSCallReducerTest : public TypedGraphTest {
return HeapConstant(f);
}
Node* StringFunction(const char* name) {
Handle<Object> m =
JSObject::GetProperty(
isolate()->global_object(),
isolate()->factory()->NewStringFromAsciiChecked("String"))
.ToHandleChecked();
Handle<JSFunction> f = Handle<JSFunction>::cast(
Object::GetProperty(
m, isolate()->factory()->NewStringFromAsciiChecked(name))
.ToHandleChecked());
return HeapConstant(f);
}
std::string op_name_for(const char* fnc) {
std::string string_fnc(fnc);
char initial = std::toupper(fnc[0]);
......@@ -391,6 +404,41 @@ TEST_F(JSCallReducerTest, MathMaxWithTwoArguments) {
IsSpeculativeToNumber(p1)));
}
// -----------------------------------------------------------------------------
// String.fromCharCode
TEST_F(JSCallReducerTest, StringFromCharCodeWithNumber) {
Node* function = StringFunction("fromCharCode");
Node* effect = graph()->start();
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::Any(), 0);
Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0,
context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsStringFromCharCode(IsSpeculativeToNumber(p0)));
}
TEST_F(JSCallReducerTest, StringFromCharCodeWithPlainPrimitive) {
Node* function = StringFunction("fromCharCode");
Node* effect = graph()->start();
Node* control = graph()->start();
Node* context = UndefinedConstant();
Node* frame_state = graph()->start();
Node* p0 = Parameter(Type::PlainPrimitive(), 0);
Node* call = graph()->NewNode(Call(3), function, UndefinedConstant(), p0,
context, frame_state, effect, control);
Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsStringFromCharCode(IsSpeculativeToNumber(p0)));
}
} // namespace compiler
} // namespace internal
} // namespace v8
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