Commit 8659c5d1 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Introduce proper JSCreateLiteralRegExp operator.

This adds a new JavaScript level operator for regexp literal creation,
similar to what we already have for array and object literals. This
once gets lowered to a call to the FastCloneRegExpStub always.

R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/1475973002

Cr-Commit-Position: refs/heads/master@{#32288}
parent 27001ca6
......@@ -1696,12 +1696,9 @@ void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
Node* closure = GetFunctionClosure();
// Create node to materialize a regular expression literal.
Node* literal_index = jsgraph()->Constant(expr->literal_index());
Node* pattern = jsgraph()->Constant(expr->pattern());
Node* flags = jsgraph()->Constant(expr->flags());
const Operator* op =
javascript()->CallRuntime(Runtime::kCreateRegExpLiteral, 4);
Node* literal = NewNode(op, closure, literal_index, pattern, flags);
const Operator* op = javascript()->CreateLiteralRegExp(
expr->pattern(), expr->flags(), expr->literal_index());
Node* literal = NewNode(op, closure);
PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(literal);
}
......
......@@ -506,7 +506,7 @@ void JSGenericLowering::LowerJSCreateClosure(Node* node) {
void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constants()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
}
......@@ -515,12 +515,26 @@ void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constants()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
}
void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Callable callable = CodeFactory::FastCloneRegExp(isolate());
Node* literal_index = jsgraph()->SmiConstant(p.index());
Node* literal_flags = jsgraph()->SmiConstant(p.flags());
Node* pattern = jsgraph()->HeapConstant(p.constant());
node->InsertInput(graph()->zone(), 1, literal_index);
node->InsertInput(graph()->zone(), 2, pattern);
node->InsertInput(graph()->zone(), 3, literal_flags);
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
Handle<String> name = OpParameter<Handle<String>>(node);
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(name));
......
......@@ -412,7 +412,7 @@ const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) {
bool operator==(CreateLiteralParameters const& lhs,
CreateLiteralParameters const& rhs) {
return lhs.constants().location() == rhs.constants().location() &&
return lhs.constant().location() == rhs.constant().location() &&
lhs.flags() == rhs.flags() && lhs.index() == rhs.index();
}
......@@ -424,18 +424,19 @@ bool operator!=(CreateLiteralParameters const& lhs,
size_t hash_value(CreateLiteralParameters const& p) {
return base::hash_combine(p.constants().location(), p.flags(), p.index());
return base::hash_combine(p.constant().location(), p.flags(), p.index());
}
std::ostream& operator<<(std::ostream& os, CreateLiteralParameters const& p) {
return os << Brief(*p.constants()) << ", " << p.flags() << ", " << p.index();
return os << Brief(*p.constant()) << ", " << p.flags() << ", " << p.index();
}
const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kJSCreateLiteralArray ||
op->opcode() == IrOpcode::kJSCreateLiteralObject);
op->opcode() == IrOpcode::kJSCreateLiteralObject ||
op->opcode() == IrOpcode::kJSCreateLiteralRegExp);
return OpParameter<CreateLiteralParameters>(op);
}
......@@ -779,6 +780,18 @@ const Operator* JSOperatorBuilder::CreateLiteralObject(
}
const Operator* JSOperatorBuilder::CreateLiteralRegExp(
Handle<String> constant_pattern, int literal_flags, int literal_index) {
CreateLiteralParameters parameters(constant_pattern, literal_flags,
literal_index);
return new (zone()) Operator1<CreateLiteralParameters>( // --
IrOpcode::kJSCreateLiteralRegExp, Operator::kNoProperties, // opcode
"JSCreateLiteralRegExp", // name
1, 1, 1, 1, 1, 2, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::CreateFunctionContext(int slot_count) {
return new (zone()) Operator1<int>( // --
IrOpcode::kJSCreateFunctionContext, Operator::kNoProperties, // opcode
......
......@@ -404,19 +404,19 @@ const CreateClosureParameters& CreateClosureParametersOf(const Operator* op);
// Defines shared information for the literal that should be created. This is
// used as parameter by JSCreateLiteralArray and JSCreateLiteralObject
// operators.
// used as parameter by JSCreateLiteralArray, JSCreateLiteralObject and
// JSCreateLiteralRegExp operators.
class CreateLiteralParameters final {
public:
CreateLiteralParameters(Handle<FixedArray> constants, int flags, int index)
: constants_(constants), flags_(flags), index_(index) {}
CreateLiteralParameters(Handle<HeapObject> constant, int flags, int index)
: constant_(constant), flags_(flags), index_(index) {}
Handle<FixedArray> constants() const { return constants_; }
Handle<HeapObject> constant() const { return constant_; }
int flags() const { return flags_; }
int index() const { return index_; }
private:
Handle<FixedArray> const constants_;
Handle<HeapObject> const constant_;
int const flags_;
int const index_;
};
......@@ -476,6 +476,8 @@ class JSOperatorBuilder final : public ZoneObject {
int literal_flags, int literal_index);
const Operator* CreateLiteralObject(Handle<FixedArray> constant_properties,
int literal_flags, int literal_index);
const Operator* CreateLiteralRegExp(Handle<String> constant_pattern,
int literal_flags, int literal_index);
const Operator* CallFunction(
size_t arity, LanguageMode language_mode,
......
......@@ -1765,7 +1765,8 @@ Reduction JSTypedLowering::ReduceJSCreateClosure(Node* node) {
Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateLiteralArray, node->opcode());
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
int const length = p.constants()->length();
Handle<FixedArray> const constants = Handle<FixedArray>::cast(p.constant());
int const length = constants->length();
int const flags = p.flags();
// Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
......@@ -1784,7 +1785,7 @@ Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) {
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
Node* literal_index = jsgraph()->SmiConstant(p.index());
Node* constant_elements = jsgraph()->HeapConstant(p.constants());
Node* constant_elements = jsgraph()->HeapConstant(constants);
node->InsertInput(graph()->zone(), 0, stub_code);
node->InsertInput(graph()->zone(), 2, literal_index);
node->InsertInput(graph()->zone(), 3, constant_elements);
......@@ -1799,8 +1800,9 @@ Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) {
Reduction JSTypedLowering::ReduceJSCreateLiteralObject(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateLiteralObject, node->opcode());
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
Handle<FixedArray> const constants = Handle<FixedArray>::cast(p.constant());
// Constants are pairs, see ObjectLiteral::properties_count().
int const length = p.constants()->length() / 2;
int const length = constants->length() / 2;
int const flags = p.flags();
// Use the FastCloneShallowObjectStub only for shallow boilerplates without
......@@ -1818,7 +1820,7 @@ Reduction JSTypedLowering::ReduceJSCreateLiteralObject(Node* node) {
Node* stub_code = jsgraph()->HeapConstant(callable.code());
Node* literal_index = jsgraph()->SmiConstant(p.index());
Node* literal_flags = jsgraph()->SmiConstant(flags);
Node* constant_elements = jsgraph()->HeapConstant(p.constants());
Node* constant_elements = jsgraph()->HeapConstant(constants);
node->InsertInput(graph()->zone(), 0, stub_code);
node->InsertInput(graph()->zone(), 2, literal_index);
node->InsertInput(graph()->zone(), 3, constant_elements);
......
......@@ -115,6 +115,7 @@
V(JSCreateClosure) \
V(JSCreateLiteralArray) \
V(JSCreateLiteralObject) \
V(JSCreateLiteralRegExp) \
V(JSLoadProperty) \
V(JSLoadNamed) \
V(JSLoadGlobal) \
......
......@@ -52,6 +52,7 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
case IrOpcode::kJSCreateArray:
case IrOpcode::kJSCreateLiteralArray:
case IrOpcode::kJSCreateLiteralObject:
case IrOpcode::kJSCreateLiteralRegExp:
// Context operations
case IrOpcode::kJSLoadDynamic:
......
......@@ -1233,7 +1233,7 @@ Type* Typer::Visitor::TypeJSCreateClosure(Node* node) {
Type* Typer::Visitor::TypeJSCreateLiteralArray(Node* node) {
return Type::None(), Type::OtherObject();
return Type::OtherObject();
}
......@@ -1242,6 +1242,11 @@ Type* Typer::Visitor::TypeJSCreateLiteralObject(Node* node) {
}
Type* Typer::Visitor::TypeJSCreateLiteralRegExp(Node* node) {
return Type::OtherObject();
}
Type* Typer::Visitor::JSLoadPropertyTyper(Type* object, Type* name, Typer* t) {
// TODO(rossberg): Use range types and sized array types to filter undefined.
if (object->IsArray() && name->Is(Type::Integral32())) {
......
......@@ -521,6 +521,7 @@ void Verifier::Visitor::Check(Node* node) {
break;
case IrOpcode::kJSCreateLiteralArray:
case IrOpcode::kJSCreateLiteralObject:
case IrOpcode::kJSCreateLiteralRegExp:
// Type is OtherObject.
CheckUpperIs(node, Type::OtherObject());
break;
......
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