Commit 7b69507c authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

[turbofan] Add handling of jumps to the serializer

Implemented branching and merging of Environments to facilitate handling of
conditional and unconditional jumps in the SerializerForBackgroundCompilation.
Added tests and printing helpers for the Environment. The internal structure
of the hints was changed to ZoneSet to support avoiding of duplicates.
Alternative implementation considerations were documented here:
https://docs.google.com/document/d/1vCQYhtFPqXafSMweSnGD8l0TKEIB6cPV5UGMHJtpy8k/edit?ts=5bf7d341#heading=h.jx4br0df5qzm

R=neis@chromium.org

Bug: v8:7790
Change-Id: Ib929c75ddb7f7fb290a5ca28d4422680a1514a4f
Reviewed-on: https://chromium-review.googlesource.com/c/1451847Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59534}
parent 0a78f454
......@@ -36,27 +36,6 @@ namespace compiler {
V(CreateFunctionContext) \
V(CreateEvalContext) \
V(Debugger) \
V(Jump) \
V(JumpConstant) \
V(JumpIfFalse) \
V(JumpIfFalseConstant) \
V(JumpIfJSReceiver) \
V(JumpIfJSReceiverConstant) \
V(JumpIfNotNull) \
V(JumpIfNotNullConstant) \
V(JumpIfNotUndefined) \
V(JumpIfNotUndefinedConstant) \
V(JumpIfNull) \
V(JumpIfNullConstant) \
V(JumpIfToBooleanTrueConstant) \
V(JumpIfToBooleanFalseConstant) \
V(JumpIfToBooleanTrue) \
V(JumpIfToBooleanFalse) \
V(JumpIfTrue) \
V(JumpIfTrueConstant) \
V(JumpIfUndefined) \
V(JumpIfUndefinedConstant) \
V(JumpLoop) \
V(PushContext) \
V(PopContext) \
V(ResumeGenerator) \
......@@ -65,10 +44,7 @@ namespace compiler {
V(StaCurrentContextSlot) \
V(SuspendGenerator) \
V(SwitchOnGeneratorState) \
V(Throw) \
V(ThrowReferenceErrorIfHole) \
V(ThrowSuperNotCalledIfHole) \
V(ThrowSuperAlreadyCalledIfNotHole)
V(Throw)
#define CLEAR_ACCUMULATOR_LIST(V) \
V(CreateEmptyObjectLiteral) \
......@@ -85,6 +61,49 @@ namespace compiler {
V(LdaNamedProperty) \
V(LdaNamedPropertyNoFeedback)
#define UNCONDITIONAL_JUMPS_LIST(V) \
V(Jump) \
V(JumpConstant) \
V(JumpLoop)
#define CONDITIONAL_JUMPS_LIST(V) \
V(JumpIfFalse) \
V(JumpIfFalseConstant) \
V(JumpIfJSReceiver) \
V(JumpIfJSReceiverConstant) \
V(JumpIfNotNull) \
V(JumpIfNotNullConstant) \
V(JumpIfNotUndefined) \
V(JumpIfNotUndefinedConstant) \
V(JumpIfNull) \
V(JumpIfNullConstant) \
V(JumpIfToBooleanTrueConstant) \
V(JumpIfToBooleanFalseConstant) \
V(JumpIfToBooleanTrue) \
V(JumpIfToBooleanFalse) \
V(JumpIfTrue) \
V(JumpIfTrueConstant) \
V(JumpIfUndefined) \
V(JumpIfUndefinedConstant)
#define INGORED_BYTECODE_LIST(V) \
V(TestEqual) \
V(TestEqualStrict) \
V(TestLessThan) \
V(TestGreaterThan) \
V(TestLessThanOrEqual) \
V(TestGreaterThanOrEqual) \
V(TestReferenceEqual) \
V(TestInstanceOf) \
V(TestIn) \
V(TestUndetectable) \
V(TestNull) \
V(TestUndefined) \
V(TestTypeOf) \
V(ThrowReferenceErrorIfHole) \
V(ThrowSuperNotCalledIfHole) \
V(ThrowSuperAlreadyCalledIfNotHole)
#define SUPPORTED_BYTECODE_LIST(V) \
V(CallAnyReceiver) \
V(CallNoFeedback) \
......@@ -114,13 +133,30 @@ namespace compiler {
V(Star) \
V(Wide) \
CLEAR_ENVIRONMENT_LIST(V) \
CLEAR_ACCUMULATOR_LIST(V)
CLEAR_ACCUMULATOR_LIST(V) \
CONDITIONAL_JUMPS_LIST(V) \
UNCONDITIONAL_JUMPS_LIST(V) \
INGORED_BYTECODE_LIST(V)
class JSHeapBroker;
template <typename T>
struct HandleComparator {
bool operator()(const Handle<T>& lhs, const Handle<T>& rhs) const {
return lhs.address() < rhs.address();
}
};
struct FunctionBlueprint {
Handle<SharedFunctionInfo> shared;
Handle<FeedbackVector> feedback_vector;
bool operator<(const FunctionBlueprint& other) const {
// A feedback vector is never used for more than one SFI, so it could
// be used for strict ordering of blueprints.
return HandleComparator<FeedbackVector>()(feedback_vector,
other.feedback_vector);
}
};
class CompilationSubject {
......@@ -137,13 +173,17 @@ class CompilationSubject {
MaybeHandle<JSFunction> closure_;
};
typedef ZoneSet<Handle<Object>, HandleComparator<Object>> ConstantsSet;
typedef ZoneSet<Handle<Map>, HandleComparator<Map>> MapsSet;
typedef ZoneSet<FunctionBlueprint> BlueprintsSet;
class Hints {
public:
explicit Hints(Zone* zone);
const ZoneVector<Handle<Object>>& constants() const;
const ZoneVector<Handle<Map>>& maps() const;
const ZoneVector<FunctionBlueprint>& function_blueprints() const;
const ConstantsSet& constants() const;
const MapsSet& maps() const;
const BlueprintsSet& function_blueprints() const;
void AddConstant(Handle<Object> constant);
void AddMap(Handle<Map> map);
......@@ -155,9 +195,9 @@ class Hints {
bool IsEmpty() const;
private:
ZoneVector<Handle<Object>> constants_;
ZoneVector<Handle<Map>> maps_;
ZoneVector<FunctionBlueprint> function_blueprints_;
ConstantsSet constants_;
MapsSet maps_;
BlueprintsSet function_blueprints_;
};
typedef ZoneVector<Hints> HintsVector;
......@@ -171,6 +211,8 @@ class SerializerForBackgroundCompilation {
Handle<JSFunction> closure);
Hints Run(); // NOTE: Returns empty for an already-serialized function.
class Environment;
private:
SerializerForBackgroundCompilation(JSHeapBroker* broker, Zone* zone,
CompilationSubject function,
......@@ -184,14 +226,14 @@ class SerializerForBackgroundCompilation {
SUPPORTED_BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
#undef DECLARE_VISIT_BYTECODE
class Environment;
void ProcessCallOrConstruct(Hints callee, base::Optional<Hints> new_target,
const HintsVector& arguments, FeedbackSlot slot,
bool with_spread = false);
void ProcessCallVarArgs(interpreter::BytecodeArrayIterator* iterator,
ConvertReceiverMode receiver_mode,
bool with_spread = false);
void ProcessJump(interpreter::BytecodeArrayIterator* iterator);
void MergeAfterJump(interpreter::BytecodeArrayIterator* iterator);
Hints RunChildSerializer(CompilationSubject function,
base::Optional<Hints> new_target,
......@@ -204,6 +246,7 @@ class SerializerForBackgroundCompilation {
JSHeapBroker* const broker_;
Zone* const zone_;
Environment* const environment_;
ZoneUnorderedMap<int, Environment*> stashed_environments_;
};
} // namespace compiler
......
......@@ -28,6 +28,8 @@ SerializerTester::SerializerTester(const char* source)
FLAG_use_ic = true;
// We need manual control over when a given function is optimized.
FLAG_always_opt = false;
// We need allocation of executable memory for the compilation.
FLAG_jitless = false;
std::string function_string = "(function() { ";
function_string += source;
......@@ -180,6 +182,36 @@ TEST(SerializeConstructWithSpread) {
"}; f(); return f;");
}
TEST(SerializeConditionalJump) {
CheckForSerializedInlinee(
"function g(callee) { callee(); };"
"function h() {};"
"function i() {};"
"let a = true;"
"g(h); g(i);"
"function f() {"
" function q() {};"
" if (a) g(q);"
" return q;"
"}; f(); return f;");
}
TEST(SerializeUnconditionalJump) {
CheckForSerializedInlinee(
"function g(callee) { callee(); };"
"function h() {};"
"function i() {};"
"let a = false;"
"g(h); g(i);"
"function f() {"
" function p() {};"
" function q() {};"
" if (a) g(q);"
" else g(p);"
" return p;"
"}; f(); return f;");
}
} // 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