Commit 394d53d1 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[turbofan] Add inlining for RegExp#test

This CL adds a TFS stub for RegExp#test and moves several checks to
the JSCallReducer. In particular, the JSCallReducer checks that
 - property {exec} on the regexp is still the original exec
 - property {lastIndex} on the regexp is a non-negative smi
The stub does not repeat these checks in release mode.

This effectively means that if the regexp is known, we can perform these
checks at compile time, and get away with a map dependency.

Bug: v8:7779, v8:7200

Change-Id: I0c6d711d4f1d2f6f325a1c02855b0e1b62e014c8
Reviewed-on: https://chromium-review.googlesource.com/1074654
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53630}
parent d6c49a72
...@@ -947,6 +947,7 @@ namespace internal { ...@@ -947,6 +947,7 @@ namespace internal {
TFJ(RegExpPrototypeStickyGetter, 0) \ TFJ(RegExpPrototypeStickyGetter, 0) \
/* ES #sec-regexp.prototype.test */ \ /* ES #sec-regexp.prototype.test */ \
TFJ(RegExpPrototypeTest, 1, kString) \ TFJ(RegExpPrototypeTest, 1, kString) \
TFS(RegExpPrototypeTestFast, kReceiver, kString) \
CPP(RegExpPrototypeToString) \ CPP(RegExpPrototypeToString) \
/* ES #sec-get-regexp.prototype.unicode */ \ /* ES #sec-get-regexp.prototype.unicode */ \
TFJ(RegExpPrototypeUnicodeGetter, 0) \ TFJ(RegExpPrototypeUnicodeGetter, 0) \
......
...@@ -114,7 +114,7 @@ TNode<Object> RegExpBuiltinsAssembler::RegExpCreate(TNode<Context> context, ...@@ -114,7 +114,7 @@ TNode<Object> RegExpBuiltinsAssembler::RegExpCreate(TNode<Context> context,
pattern, flags); pattern, flags);
} }
Node* RegExpBuiltinsAssembler::FastLoadLastIndex(Node* regexp) { TNode<Object> RegExpBuiltinsAssembler::FastLoadLastIndex(Node* regexp) {
// Load the in-object field. // Load the in-object field.
static const int field_offset = static const int field_offset =
JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize;
...@@ -672,7 +672,7 @@ Node* RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult( ...@@ -672,7 +672,7 @@ Node* RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult(
Node* const smi_zero = SmiConstant(0); Node* const smi_zero = SmiConstant(0);
if (is_fastpath) { if (is_fastpath) {
CSA_ASSERT(this, IsFastRegExpNoPrototype(context, regexp)); CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE));
} else { } else {
ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE, ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE,
"RegExp.prototype.exec"); "RegExp.prototype.exec");
...@@ -875,6 +875,51 @@ Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(Node* const context, ...@@ -875,6 +875,51 @@ Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(Node* const context,
return var_result.value(); return var_result.value();
} }
// We also return true if exec is undefined (and hence per spec)
// the original {exec} will be used.
TNode<BoolT> RegExpBuiltinsAssembler::IsFastRegExpWithOriginalExec(
TNode<Context> context, TNode<JSRegExp> object) {
CSA_ASSERT(this, TaggedIsNotSmi(object));
Label out(this);
Label check_last_index(this);
TVARIABLE(BoolT, var_result);
#ifdef V8_ENABLE_FORCE_SLOW_PATH
var_result = BoolConstant(0);
GotoIfForceSlowPath(&out);
#endif
TNode<BoolT> is_regexp = HasInstanceType(object, JS_REGEXP_TYPE);
var_result = is_regexp;
GotoIfNot(is_regexp, &out);
TNode<Context> native_context = LoadNativeContext(context);
TNode<Object> original_exec =
LoadContextElement(native_context, Context::REGEXP_EXEC_FUNCTION_INDEX);
TNode<Object> regexp_exec =
GetProperty(context, object, isolate()->factory()->exec_string());
TNode<BoolT> has_initialexec = WordEqual(regexp_exec, original_exec);
var_result = has_initialexec;
GotoIf(has_initialexec, &check_last_index);
TNode<BoolT> is_undefined = IsUndefined(regexp_exec);
var_result = is_undefined;
GotoIfNot(is_undefined, &out);
Goto(&check_last_index);
BIND(&check_last_index);
// The smi check is required to omit ToLength(lastIndex) calls with possible
// user-code execution on the fast path.
TNode<Object> last_index = FastLoadLastIndex(object);
var_result = TaggedIsPositiveSmi(last_index);
Goto(&out);
BIND(&out);
return var_result.value();
}
Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(Node* const context, Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(Node* const context,
Node* const object) { Node* const object) {
CSA_ASSERT(this, TaggedIsNotSmi(object)); CSA_ASSERT(this, TaggedIsNotSmi(object));
...@@ -1741,6 +1786,20 @@ TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) { ...@@ -1741,6 +1786,20 @@ TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) {
} }
} }
TF_BUILTIN(RegExpPrototypeTestFast, RegExpBuiltinsAssembler) {
TNode<JSRegExp> const regexp = CAST(Parameter(Descriptor::kReceiver));
TNode<String> const string = CAST(Parameter(Descriptor::kString));
TNode<Context> const context = CAST(Parameter(Descriptor::kContext));
Label if_didnotmatch(this);
CSA_ASSERT(this, IsFastRegExpWithOriginalExec(context, regexp));
RegExpPrototypeExecBodyWithoutResult(context, regexp, string, &if_didnotmatch,
true);
Return(TrueConstant());
BIND(&if_didnotmatch);
Return(FalseConstant());
}
Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string, Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string,
Node* const index, Node* const index,
Node* const is_unicode, Node* const is_unicode,
......
...@@ -41,7 +41,7 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { ...@@ -41,7 +41,7 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
Node* AllocateRegExpResult(Node* context, Node* length, Node* index, Node* AllocateRegExpResult(Node* context, Node* length, Node* index,
Node* input); Node* input);
Node* FastLoadLastIndex(Node* regexp); TNode<Object> FastLoadLastIndex(Node* regexp);
Node* SlowLoadLastIndex(Node* context, Node* regexp); Node* SlowLoadLastIndex(Node* context, Node* regexp);
Node* LoadLastIndex(Node* context, Node* regexp, bool is_fastpath); Node* LoadLastIndex(Node* context, Node* regexp, bool is_fastpath);
...@@ -89,6 +89,8 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { ...@@ -89,6 +89,8 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
// Performs fast path checks on the given object itself, but omits prototype // Performs fast path checks on the given object itself, but omits prototype
// checks. // checks.
Node* IsFastRegExpNoPrototype(Node* const context, Node* const object); Node* IsFastRegExpNoPrototype(Node* const context, Node* const object);
TNode<BoolT> IsFastRegExpWithOriginalExec(TNode<Context> context,
TNode<JSRegExp> object);
Node* IsFastRegExpNoPrototype(Node* const context, Node* const object, Node* IsFastRegExpNoPrototype(Node* const context, Node* const object,
Node* const map); Node* const map);
......
...@@ -11,10 +11,12 @@ ...@@ -11,10 +11,12 @@
#include "src/code-stubs.h" #include "src/code-stubs.h"
#include "src/compilation-dependencies.h" #include "src/compilation-dependencies.h"
#include "src/compiler/access-builder.h" #include "src/compiler/access-builder.h"
#include "src/compiler/access-info.h"
#include "src/compiler/allocation-builder.h" #include "src/compiler/allocation-builder.h"
#include "src/compiler/js-graph.h" #include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h" #include "src/compiler/linkage.h"
#include "src/compiler/node-matchers.h" #include "src/compiler/node-matchers.h"
#include "src/compiler/property-access-builder.h"
#include "src/compiler/simplified-operator.h" #include "src/compiler/simplified-operator.h"
#include "src/compiler/type-cache.h" #include "src/compiler/type-cache.h"
#include "src/feedback-vector-inl.h" #include "src/feedback-vector-inl.h"
...@@ -3507,6 +3509,8 @@ Reduction JSCallReducer::ReduceJSCall(Node* node, ...@@ -3507,6 +3509,8 @@ Reduction JSCallReducer::ReduceJSCall(Node* node,
return ReduceMapPrototypeGet(node); return ReduceMapPrototypeGet(node);
case Builtins::kMapPrototypeHas: case Builtins::kMapPrototypeHas:
return ReduceMapPrototypeHas(node); return ReduceMapPrototypeHas(node);
case Builtins::kRegExpPrototypeTest:
return ReduceRegExpPrototypeTest(node);
case Builtins::kReturnReceiver: case Builtins::kReturnReceiver:
return ReduceReturnReceiver(node); return ReduceReturnReceiver(node);
case Builtins::kStringPrototypeIndexOf: case Builtins::kStringPrototypeIndexOf:
...@@ -6741,6 +6745,99 @@ Reduction JSCallReducer::ReduceNumberParseInt(Node* node) { ...@@ -6741,6 +6745,99 @@ Reduction JSCallReducer::ReduceNumberParseInt(Node* node) {
return Changed(node); return Changed(node);
} }
Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
if (FLAG_force_slow_path) return NoChange();
if (node->op()->ValueInputCount() < 3) return NoChange();
CallParameters const& p = CallParametersOf(node->op());
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
return NoChange();
}
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* regexp = NodeProperties::GetValueInput(node, 1);
// Check if we know something about the {regexp}.
ZoneHandleSet<Map> regexp_maps;
NodeProperties::InferReceiverMapsResult result =
NodeProperties::InferReceiverMaps(regexp, effect, &regexp_maps);
bool need_map_check = false;
switch (result) {
case NodeProperties::kNoReceiverMaps:
return NoChange();
case NodeProperties::kUnreliableReceiverMaps:
need_map_check = true;
break;
case NodeProperties::kReliableReceiverMaps:
break;
}
for (auto map : regexp_maps) {
if (map->instance_type() != JS_REGEXP_TYPE) return NoChange();
}
// Compute property access info for "exec" on {resolution}.
PropertyAccessInfo ai_exec;
AccessInfoFactory access_info_factory(dependencies(), js_heap_broker(),
native_context(), graph()->zone());
if (!access_info_factory.ComputePropertyAccessInfo(
MapHandles(regexp_maps.begin(), regexp_maps.end()),
factory()->exec_string(), AccessMode::kLoad, &ai_exec)) {
return NoChange();
}
// If "exec" has been modified on {regexp}, we can't do anything.
if (!ai_exec.IsDataConstant()) return NoChange();
Handle<Object> exec_on_proto = ai_exec.constant();
if (*exec_on_proto != *isolate()->regexp_exec_function()) return NoChange();
PropertyAccessBuilder access_builder(jsgraph(), dependencies());
// Add proper dependencies on the {regexp}s [[Prototype]]s.
Handle<JSObject> holder;
if (ai_exec.holder().ToHandle(&holder)) {
access_builder.AssumePrototypesStable(native_context(),
ai_exec.receiver_maps(), holder);
}
if (need_map_check) {
effect =
graph()->NewNode(simplified()->CheckMaps(CheckMapsFlag::kNone,
regexp_maps, p.feedback()),
regexp, effect, control);
}
Node* context = NodeProperties::GetContextInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* search = NodeProperties::GetValueInput(node, 2);
Node* search_string = effect = graph()->NewNode(
simplified()->CheckString(p.feedback()), search, effect, control);
Node* lastIndex = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSRegExpLastIndex()), regexp,
effect, control);
Node* lastIndexSmi = effect = graph()->NewNode(
simplified()->CheckSmi(p.feedback()), lastIndex, effect, control);
Node* is_positive = graph()->NewNode(simplified()->NumberLessThanOrEqual(),
jsgraph()->ZeroConstant(), lastIndexSmi);
effect = graph()->NewNode(
simplified()->CheckIf(DeoptimizeReason::kNotASmi, p.feedback()),
is_positive, effect, control);
node->ReplaceInput(0, regexp);
node->ReplaceInput(1, search_string);
node->ReplaceInput(2, context);
node->ReplaceInput(3, frame_state);
node->ReplaceInput(4, effect);
node->ReplaceInput(5, control);
node->TrimInputCount(6);
NodeProperties::ChangeOp(node, javascript()->RegExpTest());
return Changed(node);
}
Graph* JSCallReducer::graph() const { return jsgraph()->graph(); } Graph* JSCallReducer::graph() const { return jsgraph()->graph(); }
Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); } Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); }
......
...@@ -25,6 +25,7 @@ class CallFrequency; ...@@ -25,6 +25,7 @@ class CallFrequency;
class CommonOperatorBuilder; class CommonOperatorBuilder;
struct FieldAccess; struct FieldAccess;
class JSGraph; class JSGraph;
class JSHeapBroker;
class JSOperatorBuilder; class JSOperatorBuilder;
class SimplifiedOperatorBuilder; class SimplifiedOperatorBuilder;
...@@ -36,11 +37,12 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { ...@@ -36,11 +37,12 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
enum Flag { kNoFlags = 0u, kBailoutOnUninitialized = 1u << 0 }; enum Flag { kNoFlags = 0u, kBailoutOnUninitialized = 1u << 0 };
typedef base::Flags<Flag> Flags; typedef base::Flags<Flag> Flags;
JSCallReducer(Editor* editor, JSGraph* jsgraph, Flags flags, JSCallReducer(Editor* editor, JSGraph* jsgraph, JSHeapBroker* js_heap_broker,
Handle<Context> native_context, Flags flags, Handle<Context> native_context,
CompilationDependencies* dependencies) CompilationDependencies* dependencies)
: AdvancedReducer(editor), : AdvancedReducer(editor),
jsgraph_(jsgraph), jsgraph_(jsgraph),
js_heap_broker_(js_heap_broker),
flags_(flags), flags_(flags),
native_context_(native_context), native_context_(native_context),
dependencies_(dependencies) {} dependencies_(dependencies) {}
...@@ -109,6 +111,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { ...@@ -109,6 +111,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
Reduction ReduceJSCall(Node* node, Handle<SharedFunctionInfo> shared); Reduction ReduceJSCall(Node* node, Handle<SharedFunctionInfo> shared);
Reduction ReduceJSCallWithArrayLike(Node* node); Reduction ReduceJSCallWithArrayLike(Node* node);
Reduction ReduceJSCallWithSpread(Node* node); Reduction ReduceJSCallWithSpread(Node* node);
Reduction ReduceRegExpPrototypeTest(Node* node);
Reduction ReduceReturnReceiver(Node* node); Reduction ReduceReturnReceiver(Node* node);
Reduction ReduceStringPrototypeIndexOf(Node* node); Reduction ReduceStringPrototypeIndexOf(Node* node);
Reduction ReduceStringPrototypeSubstring(Node* node); Reduction ReduceStringPrototypeSubstring(Node* node);
...@@ -225,6 +228,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { ...@@ -225,6 +228,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
Graph* graph() const; Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; } JSGraph* jsgraph() const { return jsgraph_; }
const JSHeapBroker* js_heap_broker() const { return js_heap_broker_; }
Isolate* isolate() const; Isolate* isolate() const;
Factory* factory() const; Factory* factory() const;
Handle<Context> native_context() const { return native_context_; } Handle<Context> native_context() const { return native_context_; }
...@@ -236,6 +240,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer { ...@@ -236,6 +240,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
CompilationDependencies* dependencies() const { return dependencies_; } CompilationDependencies* dependencies() const { return dependencies_; }
JSGraph* const jsgraph_; JSGraph* const jsgraph_;
const JSHeapBroker* const js_heap_broker_;
Flags const flags_; Flags const flags_;
Handle<Context> const native_context_; Handle<Context> const native_context_;
CompilationDependencies* const dependencies_; CompilationDependencies* const dependencies_;
......
...@@ -406,6 +406,13 @@ void JSGenericLowering::LowerJSParseInt(Node* node) { ...@@ -406,6 +406,13 @@ void JSGenericLowering::LowerJSParseInt(Node* node) {
ReplaceWithStubCall(node, callable, flags); ReplaceWithStubCall(node, callable, flags);
} }
void JSGenericLowering::LowerJSRegExpTest(Node* node) {
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kRegExpPrototypeTestFast);
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSCreateClosure(Node* node) { void JSGenericLowering::LowerJSCreateClosure(Node* node) {
CreateClosureParameters const& p = CreateClosureParametersOf(node->op()); CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
Handle<SharedFunctionInfo> const shared_info = p.shared_info(); Handle<SharedFunctionInfo> const shared_info = p.shared_info();
......
...@@ -617,7 +617,8 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) { ...@@ -617,7 +617,8 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
V(RejectPromise, Operator::kNoDeopt | Operator::kNoThrow, 3, 1) \ V(RejectPromise, Operator::kNoDeopt | Operator::kNoThrow, 3, 1) \
V(ResolvePromise, Operator::kNoDeopt | Operator::kNoThrow, 2, 1) \ V(ResolvePromise, Operator::kNoDeopt | Operator::kNoThrow, 2, 1) \
V(GetSuperConstructor, Operator::kNoWrite, 1, 1) \ V(GetSuperConstructor, Operator::kNoWrite, 1, 1) \
V(ParseInt, Operator::kNoProperties, 2, 1) V(ParseInt, Operator::kNoProperties, 2, 1) \
V(RegExpTest, Operator::kNoProperties, 2, 1)
#define BINARY_OP_LIST(V) V(Add) #define BINARY_OP_LIST(V) V(Add)
......
...@@ -816,6 +816,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final ...@@ -816,6 +816,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* ObjectIsArray(); const Operator* ObjectIsArray();
const Operator* ParseInt(); const Operator* ParseInt();
const Operator* RegExpTest();
private: private:
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
......
...@@ -209,6 +209,7 @@ ...@@ -209,6 +209,7 @@
V(JSResolvePromise) \ V(JSResolvePromise) \
V(JSStackCheck) \ V(JSStackCheck) \
V(JSObjectIsArray) \ V(JSObjectIsArray) \
V(JSRegExpTest) \
V(JSDebugger) V(JSDebugger)
#define JS_OP_LIST(V) \ #define JS_OP_LIST(V) \
......
...@@ -123,6 +123,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) { ...@@ -123,6 +123,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) {
case IrOpcode::kJSResolvePromise: case IrOpcode::kJSResolvePromise:
case IrOpcode::kJSPerformPromiseThen: case IrOpcode::kJSPerformPromiseThen:
case IrOpcode::kJSObjectIsArray: case IrOpcode::kJSObjectIsArray:
case IrOpcode::kJSRegExpTest:
return true; return true;
default: default:
......
...@@ -1145,12 +1145,12 @@ struct InliningPhase { ...@@ -1145,12 +1145,12 @@ struct InliningPhase {
CommonOperatorReducer common_reducer(data->isolate(), &graph_reducer, CommonOperatorReducer common_reducer(data->isolate(), &graph_reducer,
data->graph(), data->common(), data->graph(), data->common(),
data->machine(), temp_zone); data->machine(), temp_zone);
JSCallReducer call_reducer(&graph_reducer, data->jsgraph(), JSCallReducer call_reducer(
data->info()->is_bailout_on_uninitialized() &graph_reducer, data->jsgraph(), data->js_heap_broker(),
? JSCallReducer::kBailoutOnUninitialized data->info()->is_bailout_on_uninitialized()
: JSCallReducer::kNoFlags, ? JSCallReducer::kBailoutOnUninitialized
data->native_context(), : JSCallReducer::kNoFlags,
data->info()->dependencies()); data->native_context(), data->info()->dependencies());
JSContextSpecialization context_specialization( JSContextSpecialization context_specialization(
&graph_reducer, data->jsgraph(), &graph_reducer, data->jsgraph(),
ChooseSpecializationContext(data->info()), ChooseSpecializationContext(data->info()),
......
...@@ -1228,6 +1228,8 @@ Type Typer::Visitor::TypeJSLoadGlobal(Node* node) { ...@@ -1228,6 +1228,8 @@ Type Typer::Visitor::TypeJSLoadGlobal(Node* node) {
Type Typer::Visitor::TypeJSParseInt(Node* node) { return Type::Number(); } Type Typer::Visitor::TypeJSParseInt(Node* node) { return Type::Number(); }
Type Typer::Visitor::TypeJSRegExpTest(Node* node) { return Type::Boolean(); }
// Returns a somewhat larger range if we previously assigned // Returns a somewhat larger range if we previously assigned
// a (smaller) range to this node. This is used to speed up // a (smaller) range to this node. This is used to speed up
// the fixpoint calculation in case there appears to be a loop // the fixpoint calculation in case there appears to be a loop
......
...@@ -645,12 +645,15 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { ...@@ -645,12 +645,15 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
CheckTypeIs(node, Type::Receiver()); CheckTypeIs(node, Type::Receiver());
break; break;
case IrOpcode::kJSParseInt: case IrOpcode::kJSParseInt:
// Type is Receiver.
CheckValueInputIs(node, 0, Type::Any()); CheckValueInputIs(node, 0, Type::Any());
CheckValueInputIs(node, 1, Type::Any()); CheckValueInputIs(node, 1, Type::Any());
CheckTypeIs(node, Type::Number()); CheckTypeIs(node, Type::Number());
break; break;
case IrOpcode::kJSRegExpTest:
CheckValueInputIs(node, 0, Type::Any());
CheckValueInputIs(node, 1, Type::String());
CheckTypeIs(node, Type::Boolean());
break;
case IrOpcode::kJSCreate: case IrOpcode::kJSCreate:
// Type is Object. // Type is Object.
CheckTypeIs(node, Type::Object()); CheckTypeIs(node, Type::Object());
......
...@@ -21,7 +21,10 @@ namespace compiler { ...@@ -21,7 +21,10 @@ namespace compiler {
class JSCallReducerTest : public TypedGraphTest { class JSCallReducerTest : public TypedGraphTest {
public: public:
JSCallReducerTest() JSCallReducerTest()
: TypedGraphTest(3), javascript_(zone()), deps_(isolate(), zone()) {} : TypedGraphTest(3),
javascript_(zone()),
deps_(isolate(), zone()),
js_heap_broker(isolate()) {}
~JSCallReducerTest() override {} ~JSCallReducerTest() override {}
protected: protected:
...@@ -33,8 +36,8 @@ class JSCallReducerTest : public TypedGraphTest { ...@@ -33,8 +36,8 @@ class JSCallReducerTest : public TypedGraphTest {
// TODO(titzer): mock the GraphReducer here for better unit testing. // TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph()); GraphReducer graph_reducer(zone(), graph());
JSCallReducer reducer(&graph_reducer, &jsgraph, JSCallReducer::kNoFlags, JSCallReducer reducer(&graph_reducer, &jsgraph, &js_heap_broker,
native_context(), &deps_); JSCallReducer::kNoFlags, native_context(), &deps_);
return reducer.Reduce(node); return reducer.Reduce(node);
} }
...@@ -129,6 +132,7 @@ class JSCallReducerTest : public TypedGraphTest { ...@@ -129,6 +132,7 @@ class JSCallReducerTest : public TypedGraphTest {
private: private:
JSOperatorBuilder javascript_; JSOperatorBuilder javascript_;
CompilationDependencies deps_; CompilationDependencies deps_;
JSHeapBroker js_heap_broker;
static bool old_flag_lazy_; static bool old_flag_lazy_;
static bool old_flag_lazy_handler_; static bool old_flag_lazy_handler_;
......
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