Commit 519df935 authored by oth's avatar oth Committed by Commit bot

[Interpreter] Add support for global loads / stores / calls to BytecodeGraphBuilder.

Adds support for the LdaGlobal and StaGlobal bytecodes to the
BytecodeGraphBuilder. Also fixes a bug in the context node's parameter
index and start node inputs.

Landed on behalf of rmcilroy.

TBR=bmeuer@chromium.org,mythria@chromium.org
BUG=v8:4280
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#32049}
parent 0c1c80b2
...@@ -114,8 +114,8 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, ...@@ -114,8 +114,8 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
Node* BytecodeGraphBuilder::GetFunctionContext() { Node* BytecodeGraphBuilder::GetFunctionContext() {
if (!function_context_.is_set()) { if (!function_context_.is_set()) {
// Parameter (arity + 1) is special for the outer context of the function // Parameter (arity + 1) is special for the outer context of the function
const Operator* op = const Operator* op = common()->Parameter(
common()->Parameter(bytecode_array()->parameter_count(), "%context"); bytecode_array()->parameter_count() + 1, "%context");
Node* node = NewNode(op, graph()->start()); Node* node = NewNode(op, graph()->start());
function_context_.set(node); function_context_.set(node);
} }
...@@ -179,8 +179,10 @@ bool BytecodeGraphBuilder::CreateGraph(bool stack_check) { ...@@ -179,8 +179,10 @@ bool BytecodeGraphBuilder::CreateGraph(bool stack_check) {
// the formal parameters (including the receiver) plus context and // the formal parameters (including the receiver) plus context and
// closure. // closure.
// The additional count items are for the context and closure. // Set up the basic structure of the graph. Outputs for {Start} are the formal
int actual_parameter_count = bytecode_array()->parameter_count() + 2; // parameters (including the receiver) plus number of arguments, context and
// closure.
int actual_parameter_count = bytecode_array()->parameter_count() + 3;
graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count))); graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
Environment env(this, bytecode_array()->register_count(), Environment env(this, bytecode_array()->register_count(),
...@@ -307,74 +309,114 @@ void BytecodeGraphBuilder::VisitStar( ...@@ -307,74 +309,114 @@ void BytecodeGraphBuilder::VisitStar(
} }
void BytecodeGraphBuilder::BuildLoadGlobal(
const interpreter::BytecodeArrayIterator& iterator,
TypeofMode typeof_mode) {
Handle<Name> name =
Handle<Name>::cast(iterator.GetConstantForIndexOperand(0));
VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));
const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
Node* node = NewNode(op, BuildLoadFeedbackVector());
AddEmptyFrameStateInputs(node);
environment()->BindAccumulator(node);
}
void BytecodeGraphBuilder::VisitLdaGlobalSloppy( void BytecodeGraphBuilder::VisitLdaGlobalSloppy(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_sloppy(language_mode()));
BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
} }
void BytecodeGraphBuilder::VisitLdaGlobalStrict( void BytecodeGraphBuilder::VisitLdaGlobalStrict(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_strict(language_mode()));
BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
} }
void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppy( void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppy(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_sloppy(language_mode()));
BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
} }
void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrict( void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrict(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_strict(language_mode()));
BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
} }
void BytecodeGraphBuilder::VisitLdaGlobalSloppyWide( void BytecodeGraphBuilder::VisitLdaGlobalSloppyWide(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_sloppy(language_mode()));
BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
} }
void BytecodeGraphBuilder::VisitLdaGlobalStrictWide( void BytecodeGraphBuilder::VisitLdaGlobalStrictWide(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_strict(language_mode()));
BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
} }
void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppyWide( void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppyWide(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_sloppy(language_mode()));
BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
} }
void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrictWide( void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrictWide(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_strict(language_mode()));
BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
}
void BytecodeGraphBuilder::BuildStoreGlobal(
const interpreter::BytecodeArrayIterator& iterator) {
Handle<Name> name =
Handle<Name>::cast(iterator.GetConstantForIndexOperand(0));
VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));
Node* value = environment()->LookupAccumulator();
const Operator* op =
javascript()->StoreGlobal(language_mode(), name, feedback);
Node* node = NewNode(op, value, BuildLoadFeedbackVector());
AddEmptyFrameStateInputs(node);
} }
void BytecodeGraphBuilder::VisitStaGlobalSloppy( void BytecodeGraphBuilder::VisitStaGlobalSloppy(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_sloppy(language_mode()));
BuildStoreGlobal(iterator);
} }
void BytecodeGraphBuilder::VisitStaGlobalStrict( void BytecodeGraphBuilder::VisitStaGlobalStrict(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_strict(language_mode()));
BuildStoreGlobal(iterator);
} }
void BytecodeGraphBuilder::VisitStaGlobalSloppyWide( void BytecodeGraphBuilder::VisitStaGlobalSloppyWide(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_sloppy(language_mode()));
BuildStoreGlobal(iterator);
} }
void BytecodeGraphBuilder::VisitStaGlobalStrictWide( void BytecodeGraphBuilder::VisitStaGlobalStrictWide(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED(); DCHECK(is_strict(language_mode()));
BuildStoreGlobal(iterator);
} }
......
...@@ -86,16 +86,17 @@ class BytecodeGraphBuilder { ...@@ -86,16 +86,17 @@ class BytecodeGraphBuilder {
void UpdateControlDependencyToLeaveFunction(Node* exit); void UpdateControlDependencyToLeaveFunction(Node* exit);
void BuildBinaryOp(const Operator* op,
const interpreter::BytecodeArrayIterator& iterator);
void BuildNamedLoad(const interpreter::BytecodeArrayIterator& iterator);
Node* ProcessCallArguments(const Operator* call_op, Node* ProcessCallArguments(const Operator* call_op,
interpreter::Register callee, interpreter::Register callee,
interpreter::Register receiver, size_t arity); interpreter::Register receiver, size_t arity);
void BuildLoadGlobal(const interpreter::BytecodeArrayIterator& iterator,
TypeofMode typeof_mode);
void BuildStoreGlobal(const interpreter::BytecodeArrayIterator& iterator);
void BuildNamedLoad(const interpreter::BytecodeArrayIterator& iterator);
void BuildCall(const interpreter::BytecodeArrayIterator& iterator); void BuildCall(const interpreter::BytecodeArrayIterator& iterator);
void BuildBinaryOp(const Operator* op,
const interpreter::BytecodeArrayIterator& iterator);
// Growth increment for the temporary buffer used to construct input lists to // Growth increment for the temporary buffer used to construct input lists to
// new nodes. // new nodes.
......
...@@ -179,7 +179,7 @@ enum class ToPrimitiveHint { kDefault, kNumber, kString }; ...@@ -179,7 +179,7 @@ enum class ToPrimitiveHint { kDefault, kNumber, kString };
enum class OrdinaryToPrimitiveHint { kNumber, kString }; enum class OrdinaryToPrimitiveHint { kNumber, kString };
enum TypeofMode { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; enum TypeofMode : int { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
enum MutableMode { enum MutableMode {
......
...@@ -156,6 +156,8 @@ struct ExpectedSnippet { ...@@ -156,6 +156,8 @@ struct ExpectedSnippet {
} }
inline Handle<Object> parameter(int i) const { inline Handle<Object> parameter(int i) const {
DCHECK_GE(i, 0);
DCHECK_LT(i, N);
return return_value_and_parameters[1 + i]; return return_value_and_parameters[1 + i];
} }
}; };
...@@ -366,6 +368,52 @@ TEST(BytecodeGraphBuilderPropertyCall) { ...@@ -366,6 +368,52 @@ TEST(BytecodeGraphBuilderPropertyCall) {
} }
} }
TEST(BytecodeGraphBuilderGlobals) {
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone* zone = scope.main_zone();
Factory* factory = isolate->factory();
ExpectedSnippet<0> snippets[] = {
{"var global = 321;\n function f() { return global; };\n f();",
{factory->NewNumberFromInt(321)}},
{"var global = 321;\n"
"function f() { global = 123; return global };\n f();",
{factory->NewNumberFromInt(123)}},
{"var global = function() { return 'abc'};\n"
"function f() { return global(); };\n f();",
{factory->NewStringFromStaticChars("abc")}},
{"var global = 456;\n"
"function f() { 'use strict'; return global; };\n f();",
{factory->NewNumberFromInt(456)}},
{"var global = 987;\n"
"function f() { 'use strict'; global = 789; return global };\n f();",
{factory->NewNumberFromInt(789)}},
{"var global = function() { return 'xyz'};\n"
"function f() { 'use strict'; return global(); };\n f();",
{factory->NewStringFromStaticChars("xyz")}},
{"var global = 'abc'; var global_obj = {val:123};\n"
"function f() {\n" REPEAT_127(
SPACE, " var b = global_obj.name;\n") "return global; };\n f();\n",
{factory->NewStringFromStaticChars("abc")}},
{"var global = 'abc'; var global_obj = {val:123};\n"
"function f() { 'use strict';\n" REPEAT_127(
SPACE, " var b = global_obj.name;\n") "global = 'xyz'; return "
"global };\n f();\n",
{factory->NewStringFromStaticChars("xyz")}},
// TODO(rmcilroy): Add tests for typeof_mode once we have typeof support.
};
size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
for (size_t i = 0; i < num_snippets; i++) {
BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
CHECK(return_value->SameValue(*snippets[i].return_value()));
}
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -440,6 +440,93 @@ TEST_F(BytecodeGraphBuilderTest, CallProperty2) { ...@@ -440,6 +440,93 @@ TEST_F(BytecodeGraphBuilderTest, CallProperty2) {
} }
TEST_F(BytecodeGraphBuilderTest, LoadGlobal) {
const TypeofMode kTypeOfModes[] = {TypeofMode::NOT_INSIDE_TYPEOF,
TypeofMode::INSIDE_TYPEOF};
const bool kWideBytecode[] = {false, true};
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
TRACED_FOREACH(TypeofMode, typeof_mode, kTypeOfModes) {
TRACED_FOREACH(bool, wide_bytecode, kWideBytecode) {
FeedbackVectorSpec feedback_spec(zone());
if (wide_bytecode) {
for (int i = 0; i < 128; i++) {
feedback_spec.AddLoadICSlot();
}
}
FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
Handle<TypeFeedbackVector> vector =
NewTypeFeedbackVector(isolate(), &feedback_spec);
interpreter::BytecodeArrayBuilder array_builder(isolate(), zone());
array_builder.set_locals_count(0);
array_builder.set_context_count(0);
array_builder.set_parameter_count(1);
Handle<Name> name = GetName(isolate(), "global");
size_t name_index = array_builder.GetConstantPoolEntry(name);
array_builder.LoadGlobal(name_index, vector->GetIndex(slot),
language_mode, typeof_mode)
.Return();
Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray(),
vector, language_mode);
Node* ret = graph->end()->InputAt(0);
Node* start = graph->start();
Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start);
Matcher<Node*> load_global_matcher = IsJSLoadGlobal(
name, typeof_mode, feedback_vector_matcher, start, start);
EXPECT_THAT(ret, IsReturn(load_global_matcher, _, _));
}
}
}
}
TEST_F(BytecodeGraphBuilderTest, StoreGlobal) {
const bool kWideBytecode[] = {false, true};
TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
TRACED_FOREACH(bool, wide_bytecode, kWideBytecode) {
FeedbackVectorSpec feedback_spec(zone());
if (wide_bytecode) {
for (int i = 0; i < 128; i++) {
feedback_spec.AddStoreICSlot();
}
}
FeedbackVectorSlot slot = feedback_spec.AddStoreICSlot();
Handle<TypeFeedbackVector> vector =
NewTypeFeedbackVector(isolate(), &feedback_spec);
interpreter::BytecodeArrayBuilder array_builder(isolate(), zone());
array_builder.set_locals_count(0);
array_builder.set_context_count(0);
array_builder.set_parameter_count(1);
Handle<Name> name = GetName(isolate(), "global");
size_t name_index = array_builder.GetConstantPoolEntry(name);
array_builder.LoadLiteral(Smi::FromInt(321))
.StoreGlobal(name_index, vector->GetIndex(slot), language_mode)
.Return();
Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray(), vector,
language_mode);
Node* ret = graph->end()->InputAt(0);
Node* start = graph->start();
Matcher<Node*> value_matcher = IsNumberConstant(321);
Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start);
Matcher<Node*> store_global_matcher = IsJSStoreGlobal(
name, value_matcher, feedback_vector_matcher, start, start);
EXPECT_THAT(ret, IsReturn(_, store_global_matcher, _));
}
}
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "src/compiler/node-properties.h" #include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h" #include "src/compiler/simplified-operator.h"
#include "src/handles-inl.h" #include "src/handles-inl.h"
#include "src/objects.h"
using testing::_; using testing::_;
using testing::MakeMatcher; using testing::MakeMatcher;
...@@ -1481,6 +1482,115 @@ class IsJSLoadNamedMatcher final : public NodeMatcher { ...@@ -1481,6 +1482,115 @@ class IsJSLoadNamedMatcher final : public NodeMatcher {
}; };
class IsJSLoadGlobalMatcher final : public NodeMatcher {
public:
IsJSLoadGlobalMatcher(const Matcher<Handle<Name>>& name_matcher,
const Matcher<TypeofMode> typeof_mode_matcher,
const Matcher<Node*>& feedback_vector_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher)
: NodeMatcher(IrOpcode::kJSLoadGlobal),
name_matcher_(name_matcher),
typeof_mode_matcher_(typeof_mode_matcher),
feedback_vector_matcher_(feedback_vector_matcher),
effect_matcher_(effect_matcher),
control_matcher_(control_matcher) {}
void DescribeTo(std::ostream* os) const final {
NodeMatcher::DescribeTo(os);
*os << " whose name (";
name_matcher_.DescribeTo(os);
*os << "), typeof mode (";
typeof_mode_matcher_.DescribeTo(os);
*os << "), feedback vector (";
feedback_vector_matcher_.DescribeTo(os);
*os << "), effect (";
effect_matcher_.DescribeTo(os);
*os << "), and control (";
control_matcher_.DescribeTo(os);
*os << ")";
}
bool MatchAndExplain(Node* node, MatchResultListener* listener) const final {
return (NodeMatcher::MatchAndExplain(node, listener) &&
PrintMatchAndExplain(
OpParameter<const LoadGlobalParameters>(node).name(), "name",
name_matcher_, listener) &&
PrintMatchAndExplain(
OpParameter<const LoadGlobalParameters>(node).typeof_mode(),
"typeof mode", typeof_mode_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
"feedback vector", feedback_vector_matcher_,
listener) &&
PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
effect_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetControlInput(node),
"control", control_matcher_, listener));
}
private:
const Matcher<Handle<Name>> name_matcher_;
const Matcher<TypeofMode> typeof_mode_matcher_;
const Matcher<Node*> feedback_vector_matcher_;
const Matcher<Node*> effect_matcher_;
const Matcher<Node*> control_matcher_;
};
class IsJSStoreGlobalMatcher final : public NodeMatcher {
public:
IsJSStoreGlobalMatcher(const Matcher<Handle<Name>>& name_matcher,
const Matcher<Node*>& value_matcher,
const Matcher<Node*>& feedback_vector_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher)
: NodeMatcher(IrOpcode::kJSStoreGlobal),
name_matcher_(name_matcher),
value_matcher_(value_matcher),
feedback_vector_matcher_(feedback_vector_matcher),
effect_matcher_(effect_matcher),
control_matcher_(control_matcher) {}
void DescribeTo(std::ostream* os) const final {
NodeMatcher::DescribeTo(os);
*os << " whose name (";
name_matcher_.DescribeTo(os);
*os << "), value (";
value_matcher_.DescribeTo(os);
*os << "), feedback vector (";
feedback_vector_matcher_.DescribeTo(os);
*os << "), effect (";
effect_matcher_.DescribeTo(os);
*os << "), and control (";
control_matcher_.DescribeTo(os);
*os << ")";
}
bool MatchAndExplain(Node* node, MatchResultListener* listener) const final {
return (NodeMatcher::MatchAndExplain(node, listener) &&
PrintMatchAndExplain(
OpParameter<const StoreGlobalParameters>(node).name(), "name",
name_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
"value", value_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
"feedback vector", feedback_vector_matcher_,
listener) &&
PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
effect_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetControlInput(node),
"control", control_matcher_, listener));
}
private:
const Matcher<Handle<Name>> name_matcher_;
const Matcher<Node*> value_matcher_;
const Matcher<Node*> feedback_vector_matcher_;
const Matcher<Node*> effect_matcher_;
const Matcher<Node*> control_matcher_;
};
class IsJSCallFunctionMatcher final : public NodeMatcher { class IsJSCallFunctionMatcher final : public NodeMatcher {
public: public:
IsJSCallFunctionMatcher(const std::vector<Matcher<Node*>>& value_matchers, IsJSCallFunctionMatcher(const std::vector<Matcher<Node*>>& value_matchers,
...@@ -2117,6 +2227,28 @@ Matcher<Node*> IsJSLoadNamed(const Handle<Name> name, ...@@ -2117,6 +2227,28 @@ Matcher<Node*> IsJSLoadNamed(const Handle<Name> name,
} }
Matcher<Node*> IsJSLoadGlobal(const Handle<Name> name,
const TypeofMode typeof_mode,
const Matcher<Node*>& feedback_vector_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) {
return MakeMatcher(
new IsJSLoadGlobalMatcher(name, typeof_mode, feedback_vector_matcher,
effect_matcher, control_matcher));
}
Matcher<Node*> IsJSStoreGlobal(const Handle<Name> name,
const Matcher<Node*>& value_matcher,
const Matcher<Node*>& feedback_vector_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) {
return MakeMatcher(
new IsJSStoreGlobalMatcher(name, value_matcher, feedback_vector_matcher,
effect_matcher, control_matcher));
}
Matcher<Node*> IsJSCallFunction(std::vector<Matcher<Node*>> value_matchers, Matcher<Node*> IsJSCallFunction(std::vector<Matcher<Node*>> value_matchers,
const Matcher<Node*>& effect_matcher, const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) { const Matcher<Node*>& control_matcher) {
......
...@@ -19,6 +19,7 @@ class Handle; ...@@ -19,6 +19,7 @@ class Handle;
class HeapObject; class HeapObject;
template <class> template <class>
class TypeImpl; class TypeImpl;
enum TypeofMode : int;
struct ZoneTypeConfig; struct ZoneTypeConfig;
typedef TypeImpl<ZoneTypeConfig> Type; typedef TypeImpl<ZoneTypeConfig> Type;
...@@ -362,6 +363,16 @@ Matcher<Node*> IsJSLoadNamed(const Handle<Name> name, ...@@ -362,6 +363,16 @@ Matcher<Node*> IsJSLoadNamed(const Handle<Name> name,
const Matcher<Node*>& feedback_vector_matcher, const Matcher<Node*>& feedback_vector_matcher,
const Matcher<Node*>& effect_matcher, const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher); const Matcher<Node*>& control_matcher);
Matcher<Node*> IsJSLoadGlobal(const Handle<Name> name,
const TypeofMode typeof_mode,
const Matcher<Node*>& feedback_vector_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsJSStoreGlobal(const Handle<Name> name,
const Matcher<Node*>& value,
const Matcher<Node*>& feedback_vector_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsJSCallFunction(std::vector<Matcher<Node*>> value_matchers, Matcher<Node*> IsJSCallFunction(std::vector<Matcher<Node*>> value_matchers,
const Matcher<Node*>& effect_matcher, const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher); const Matcher<Node*>& control_matcher);
......
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