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 ...@@ -75,13 +75,8 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final
Reduction ReduceNumberIsSafeInteger(Node* node); Reduction ReduceNumberIsSafeInteger(Node* node);
Reduction ReduceNumberParseInt(Node* node); Reduction ReduceNumberParseInt(Node* node);
Reduction ReduceObjectCreate(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 ReduceStringSlice(Node* node);
Reduction ReduceStringToLowerCaseIntl(Node* node); Reduction ReduceStringConcat(Node* node);
Reduction ReduceStringToUpperCaseIntl(Node* node);
Reduction ReduceArrayBufferIsView(Node* node); Reduction ReduceArrayBufferIsView(Node* node);
Reduction ReduceArrayBufferViewAccessor(Node* node, Reduction ReduceArrayBufferViewAccessor(Node* node,
InstanceType instance_type, InstanceType instance_type,
......
This diff is collapsed.
...@@ -100,6 +100,16 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { ...@@ -100,6 +100,16 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
Reduction ReduceStringPrototypeIndexOf(Node* node); Reduction ReduceStringPrototypeIndexOf(Node* node);
Reduction ReduceStringPrototypeStringAt( Reduction ReduceStringPrototypeStringAt(
const Operator* string_access_operator, Node* node); 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 ReduceAsyncFunctionPromiseCreate(Node* node);
Reduction ReduceAsyncFunctionPromiseRelease(Node* node); Reduction ReduceAsyncFunctionPromiseRelease(Node* node);
Reduction ReducePromiseCapabilityDefaultReject(Node* node); Reduction ReducePromiseCapabilityDefaultReject(Node* node);
......
...@@ -143,6 +143,8 @@ Reduction JSCreateLowering::Reduce(Node* node) { ...@@ -143,6 +143,8 @@ Reduction JSCreateLowering::Reduce(Node* node) {
return ReduceJSCreateClosure(node); return ReduceJSCreateClosure(node);
case IrOpcode::kJSCreateIterResultObject: case IrOpcode::kJSCreateIterResultObject:
return ReduceJSCreateIterResultObject(node); return ReduceJSCreateIterResultObject(node);
case IrOpcode::kJSCreateStringIterator:
return ReduceJSCreateStringIterator(node);
case IrOpcode::kJSCreateKeyValueArray: case IrOpcode::kJSCreateKeyValueArray:
return ReduceJSCreateKeyValueArray(node); return ReduceJSCreateKeyValueArray(node);
case IrOpcode::kJSCreatePromise: case IrOpcode::kJSCreatePromise:
...@@ -982,6 +984,28 @@ Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) { ...@@ -982,6 +984,28 @@ Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
return Changed(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) { Reduction JSCreateLowering::ReduceJSCreateKeyValueArray(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateKeyValueArray, node->opcode()); DCHECK_EQ(IrOpcode::kJSCreateKeyValueArray, node->opcode());
Node* key = NodeProperties::GetValueInput(node, 0); Node* key = NodeProperties::GetValueInput(node, 0);
......
...@@ -53,6 +53,7 @@ class V8_EXPORT_PRIVATE JSCreateLowering final ...@@ -53,6 +53,7 @@ class V8_EXPORT_PRIVATE JSCreateLowering final
Reduction ReduceJSCreateBoundFunction(Node* node); Reduction ReduceJSCreateBoundFunction(Node* node);
Reduction ReduceJSCreateClosure(Node* node); Reduction ReduceJSCreateClosure(Node* node);
Reduction ReduceJSCreateIterResultObject(Node* node); Reduction ReduceJSCreateIterResultObject(Node* node);
Reduction ReduceJSCreateStringIterator(Node* node);
Reduction ReduceJSCreateKeyValueArray(Node* node); Reduction ReduceJSCreateKeyValueArray(Node* node);
Reduction ReduceJSCreatePromise(Node* node); Reduction ReduceJSCreatePromise(Node* node);
Reduction ReduceJSCreateLiteralArrayOrObject(Node* node); Reduction ReduceJSCreateLiteralArrayOrObject(Node* node);
......
...@@ -418,6 +418,10 @@ void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) { ...@@ -418,6 +418,10 @@ void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering. UNREACHABLE(); // Eliminated in typed lowering.
} }
void JSGenericLowering::LowerJSCreateStringIterator(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering.
}
void JSGenericLowering::LowerJSCreateKeyValueArray(Node* node) { void JSGenericLowering::LowerJSCreateKeyValueArray(Node* node) {
UNREACHABLE(); // Eliminated in typed lowering. UNREACHABLE(); // Eliminated in typed lowering.
} }
......
...@@ -569,6 +569,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) { ...@@ -569,6 +569,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
V(ToString, Operator::kNoProperties, 1, 1) \ V(ToString, Operator::kNoProperties, 1, 1) \
V(Create, Operator::kNoProperties, 2, 1) \ V(Create, Operator::kNoProperties, 2, 1) \
V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \ V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \
V(CreateStringIterator, Operator::kEliminatable, 1, 1) \
V(CreateKeyValueArray, Operator::kEliminatable, 2, 1) \ V(CreateKeyValueArray, Operator::kEliminatable, 2, 1) \
V(CreatePromise, Operator::kEliminatable, 0, 1) \ V(CreatePromise, Operator::kEliminatable, 0, 1) \
V(HasProperty, Operator::kNoProperties, 2, 1) \ V(HasProperty, Operator::kNoProperties, 2, 1) \
......
...@@ -658,6 +658,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final ...@@ -658,6 +658,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
Handle<FeedbackCell> feedback_cell, Handle<FeedbackCell> feedback_cell,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
const Operator* CreateIterResultObject(); const Operator* CreateIterResultObject();
const Operator* CreateStringIterator();
const Operator* CreateKeyValueArray(); const Operator* CreateKeyValueArray();
const Operator* CreatePromise(); const Operator* CreatePromise();
const Operator* CreateLiteralArray(Handle<ConstantElementsPair> constant, const Operator* CreateLiteralArray(Handle<ConstantElementsPair> constant,
......
...@@ -515,6 +515,27 @@ MaybeHandle<Map> NodeProperties::GetMapWitness(Node* node) { ...@@ -515,6 +515,27 @@ MaybeHandle<Map> NodeProperties::GetMapWitness(Node* node) {
return MaybeHandle<Map>(); 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 // static
bool NodeProperties::NoObservableSideEffectBetween(Node* effect, bool NodeProperties::NoObservableSideEffectBetween(Node* effect,
Node* dominator) { Node* dominator) {
......
...@@ -155,6 +155,8 @@ class V8_EXPORT_PRIVATE NodeProperties final { ...@@ -155,6 +155,8 @@ class V8_EXPORT_PRIVATE NodeProperties final {
Node* receiver, Node* effect, ZoneHandleSet<Map>* maps_return); Node* receiver, Node* effect, ZoneHandleSet<Map>* maps_return);
static MaybeHandle<Map> GetMapWitness(Node* node); 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 // 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 // between the {effect} and it's {dominator}. Aborts the walk if there's join
......
...@@ -140,6 +140,7 @@ ...@@ -140,6 +140,7 @@
V(JSCreateClosure) \ V(JSCreateClosure) \
V(JSCreateGeneratorObject) \ V(JSCreateGeneratorObject) \
V(JSCreateIterResultObject) \ V(JSCreateIterResultObject) \
V(JSCreateStringIterator) \
V(JSCreateKeyValueArray) \ V(JSCreateKeyValueArray) \
V(JSCreatePromise) \ V(JSCreatePromise) \
V(JSCreateLiteralArray) \ V(JSCreateLiteralArray) \
......
...@@ -1225,6 +1225,10 @@ Type* Typer::Visitor::TypeJSCreateIterResultObject(Node* node) { ...@@ -1225,6 +1225,10 @@ Type* Typer::Visitor::TypeJSCreateIterResultObject(Node* node) {
return Type::OtherObject(); return Type::OtherObject();
} }
Type* Typer::Visitor::TypeJSCreateStringIterator(Node* node) {
return Type::OtherObject();
}
Type* Typer::Visitor::TypeJSCreateKeyValueArray(Node* node) { Type* Typer::Visitor::TypeJSCreateKeyValueArray(Node* node) {
return Type::OtherObject(); return Type::OtherObject();
} }
...@@ -1958,9 +1962,13 @@ Type* Typer::Visitor::StringFromCodePointTyper(Type* type, Typer* t) { ...@@ -1958,9 +1962,13 @@ Type* Typer::Visitor::StringFromCodePointTyper(Type* type, Typer* t) {
Type* Typer::Visitor::TypeStringCharAt(Node* node) { return Type::String(); } 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) { Type* Typer::Visitor::TypeStringCharCodeAt(Node* node) {
return typer_->cache_.kUint16; return typer_->cache_.kUint16;
......
...@@ -677,6 +677,10 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { ...@@ -677,6 +677,10 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
// Type is OtherObject. // Type is OtherObject.
CheckTypeIs(node, Type::OtherObject()); CheckTypeIs(node, Type::OtherObject());
break; break;
case IrOpcode::kJSCreateStringIterator:
// Type is OtherObject.
CheckTypeIs(node, Type::OtherObject());
break;
case IrOpcode::kJSCreateKeyValueArray: case IrOpcode::kJSCreateKeyValueArray:
// Type is OtherObject. // Type is OtherObject.
CheckTypeIs(node, Type::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) { ...@@ -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 compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -67,6 +67,19 @@ class JSCallReducerTest : public TypedGraphTest { ...@@ -67,6 +67,19 @@ class JSCallReducerTest : public TypedGraphTest {
return HeapConstant(f); 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 op_name_for(const char* fnc) {
std::string string_fnc(fnc); std::string string_fnc(fnc);
char initial = std::toupper(fnc[0]); char initial = std::toupper(fnc[0]);
...@@ -391,6 +404,41 @@ TEST_F(JSCallReducerTest, MathMaxWithTwoArguments) { ...@@ -391,6 +404,41 @@ TEST_F(JSCallReducerTest, MathMaxWithTwoArguments) {
IsSpeculativeToNumber(p1))); 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 compiler
} // namespace internal } // namespace internal
} // namespace v8 } // 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