Commit 2600bba4 authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

[turbofan] Enhance the serializer for background compilation phase

This CL adds handling for almost all calls, and for some load and store
bytecodes in the serializer and marks the relevant call targets as
"serialized for compilation".

Design doc:
https://docs.google.com/document/d/1vCQYhtFPqXafSMweSnGD8l0TKEIB6cPV5UGMHJtpy8k/edit?ts=5bf7d341

Bug: v8:7790
Change-Id: I2bd24c1b0541e83c108422b66902a5b979f1e1a8
Reviewed-on: https://chromium-review.googlesource.com/c/1351014Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58873}
parent fab59bbb
...@@ -319,6 +319,14 @@ class JSFunctionData : public JSObjectData { ...@@ -319,6 +319,14 @@ class JSFunctionData : public JSObjectData {
void Serialize(JSHeapBroker* broker); void Serialize(JSHeapBroker* broker);
void SetSerializedForCompilation(JSHeapBroker* broker) {
CHECK(!serialized_for_compilation_);
serialized_for_compilation_ = true;
}
bool serialized_for_compilation() const {
return serialized_for_compilation_;
}
ContextData* context() const { return context_; } ContextData* context() const { return context_; }
NativeContextData* native_context() const { return native_context_; } NativeContextData* native_context() const { return native_context_; }
MapData* initial_map() const { return initial_map_; } MapData* initial_map() const { return initial_map_; }
...@@ -335,6 +343,7 @@ class JSFunctionData : public JSObjectData { ...@@ -335,6 +343,7 @@ class JSFunctionData : public JSObjectData {
bool PrototypeRequiresRuntimeLookup_; bool PrototypeRequiresRuntimeLookup_;
bool serialized_ = false; bool serialized_ = false;
bool serialized_for_compilation_ = false;
ContextData* context_ = nullptr; ContextData* context_ = nullptr;
NativeContextData* native_context_ = nullptr; NativeContextData* native_context_ = nullptr;
...@@ -2629,6 +2638,16 @@ void JSFunctionRef::Serialize() { ...@@ -2629,6 +2638,16 @@ void JSFunctionRef::Serialize() {
data()->AsJSFunction()->Serialize(broker()); data()->AsJSFunction()->Serialize(broker());
} }
void JSFunctionRef::SetSerializedForCompilation() {
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsJSFunction()->SetSerializedForCompilation(broker());
}
bool JSFunctionRef::serialized_for_compilation() const {
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
return data()->AsJSFunction()->serialized_for_compilation();
}
void JSObjectRef::SerializeObjectCreateMap() { void JSObjectRef::SerializeObjectCreateMap() {
if (broker()->mode() == JSHeapBroker::kDisabled) return; if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing); CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
......
...@@ -234,6 +234,9 @@ class JSFunctionRef : public JSObjectRef { ...@@ -234,6 +234,9 @@ class JSFunctionRef : public JSObjectRef {
bool PrototypeRequiresRuntimeLookup() const; bool PrototypeRequiresRuntimeLookup() const;
void Serialize(); void Serialize();
void SetSerializedForCompilation();
bool serialized_for_compilation() const;
// The following are available only after calling Serialize(). // The following are available only after calling Serialize().
ObjectRef prototype() const; ObjectRef prototype() const;
......
...@@ -289,6 +289,15 @@ bool JSInliner::DetermineCallTarget( ...@@ -289,6 +289,15 @@ bool JSInliner::DetermineCallTarget(
if (match.HasValue() && match.Value()->IsJSFunction()) { if (match.HasValue() && match.Value()->IsJSFunction()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value()); Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value());
JSFunctionRef ref(broker(), function);
if (FLAG_concurrent_inlining && !ref.serialized_for_compilation()) {
broker()->Trace("Possibly missed opportunity to inline a function ");
if (FLAG_trace_heap_broker) {
match.Value()->ShortPrint();
PrintF(")\n");
}
}
// Disallow cross native-context inlining for now. This means that all parts // Disallow cross native-context inlining for now. This means that all parts
// of the resulting code will operate on the same global object. This also // of the resulting code will operate on the same global object. This also
// prevents cross context leaks, where we could inline functions from a // prevents cross context leaks, where we could inline functions from a
......
...@@ -17,52 +17,495 @@ namespace compiler { ...@@ -17,52 +17,495 @@ namespace compiler {
class SerializerForBackgroundCompilation::Environment : public ZoneObject { class SerializerForBackgroundCompilation::Environment : public ZoneObject {
public: public:
explicit Environment(Zone* zone, Isolate* isolate, explicit Environment(Zone* zone, Isolate* isolate, int register_count,
MaybeHandle<JSFunction> closure); int parameter_count);
Environment(SerializerForBackgroundCompilation* serializer, Isolate* isolate,
int register_count, int parameter_count, Hints receiver,
const HintsVector& arguments);
int parameter_count() const { return parameter_count_; }
int register_count() const { return register_count_; }
// Remove all hints except those for the return value.
void Clear();
// Getters for the hints gathered until now (constants or maps).
const Hints& LookupAccumulator();
const Hints& LookupReturnValue();
const Hints& LookupRegister(interpreter::Register the_register);
// Setters for hints.
void AddAccumulatorHints(const Hints& hints);
void ReplaceAccumulatorHint(Handle<Object> hint);
void SetAccumulatorHints(const Hints& hints);
void ClearAccumulatorHints();
void AddReturnValueHints(const Hints& hints);
void SetRegisterHints(interpreter::Register the_register, const Hints& hints);
private: private:
explicit Environment(Zone* zone)
: environment_hints_(zone),
return_value_hints_(zone),
register_count_(0),
parameter_count_(0),
empty_hints_(Hints(zone)) {}
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
int RegisterToLocalIndex(interpreter::Register the_register) const;
Zone* zone_; Zone* zone_;
MaybeHandle<JSFunction> closure_; // environment_hints_ contains best-effort guess for state of the registers,
// the accumulator and the parameters. The structure is inspired by
// BytecodeGraphBuilder::Environment and looks like:
// hints: receiver | parameters | registers | accumulator
// indices: 0 register_base() accumulator_base()
HintsVector environment_hints_;
Hints return_value_hints_;
const int register_count_;
const int parameter_count_;
int register_base() const { return parameter_count_ + 1; }
int accumulator_base() const { return register_base() + register_count_; }
static const int kReceiverIndex = 0;
static const int kParameterBase = 1;
const Hints empty_hints_;
}; };
SerializerForBackgroundCompilation::Environment::Environment( SerializerForBackgroundCompilation::Environment::Environment(
Zone* zone, Isolate* isolate, MaybeHandle<JSFunction> closure) Zone* zone, Isolate* isolate, int register_count, int parameter_count)
: zone_(zone), closure_(closure) { : zone_(zone),
USE(isolate); environment_hints_(register_count + parameter_count + 2, Hints(zone),
zone),
return_value_hints_(zone),
register_count_(register_count),
parameter_count_(parameter_count),
empty_hints_(Hints(zone)) {}
SerializerForBackgroundCompilation::Environment::Environment(
SerializerForBackgroundCompilation* serializer, Isolate* isolate,
int register_count, int parameter_count, Hints receiver,
const HintsVector& arguments)
: Environment(serializer->zone(), isolate, register_count,
parameter_count) {
environment_hints_[kReceiverIndex] = receiver;
size_t param_count = static_cast<size_t>(parameter_count);
// Copy the hints for the actually passed arguments, at most up to
// the parameter_count.
for (size_t i = 0; i < std::min(arguments.size(), param_count); ++i) {
environment_hints_[kParameterBase + i] = arguments[i];
}
Hints undefined_hint(serializer->zone());
undefined_hint.push_back(
serializer->broker()->isolate()->factory()->undefined_value());
// Pad the rest with "undefined".
for (size_t i = arguments.size(); i < param_count; ++i) {
environment_hints_[kParameterBase + i] = undefined_hint;
}
}
int SerializerForBackgroundCompilation::Environment::RegisterToLocalIndex(
interpreter::Register the_register) const {
if (the_register.is_parameter()) {
return kParameterBase + the_register.ToParameterIndex(parameter_count());
} else {
return register_base() + the_register.index();
}
}
void SerializerForBackgroundCompilation::Environment::Clear() {
environment_hints_ =
HintsVector(environment_hints_.size(), empty_hints_, zone());
}
const Hints&
SerializerForBackgroundCompilation::Environment::LookupAccumulator() {
return environment_hints_[accumulator_base()];
}
const Hints&
SerializerForBackgroundCompilation::Environment::LookupReturnValue() {
return return_value_hints_;
}
const Hints& SerializerForBackgroundCompilation::Environment::LookupRegister(
interpreter::Register the_register) {
// TODO(mslekova): We also want to gather hints for the context and
// we already have data about the closure, so eventually more useful
// info should be returned here instead of empty hints.
if (the_register.is_current_context() || the_register.is_function_closure()) {
return empty_hints_;
}
int local_index = RegisterToLocalIndex(the_register);
DCHECK(static_cast<size_t>(local_index) < environment_hints_.size());
return environment_hints_[local_index];
}
void SerializerForBackgroundCompilation::Environment::AddAccumulatorHints(
const Hints& hints) {
for (auto v : hints) {
environment_hints_[accumulator_base()].push_back(v);
}
}
void SerializerForBackgroundCompilation::Environment::ReplaceAccumulatorHint(
Handle<Object> hint) {
ClearAccumulatorHints();
environment_hints_[accumulator_base()].push_back(hint);
}
void SerializerForBackgroundCompilation::Environment::ClearAccumulatorHints() {
SetAccumulatorHints(empty_hints_);
}
void SerializerForBackgroundCompilation::Environment::SetAccumulatorHints(
const Hints& hints) {
environment_hints_[accumulator_base()] = hints;
}
void SerializerForBackgroundCompilation::Environment::AddReturnValueHints(
const Hints& hints) {
for (auto v : hints) {
return_value_hints_.push_back(v);
}
}
void SerializerForBackgroundCompilation::Environment::SetRegisterHints(
interpreter::Register the_register, const Hints& hints) {
int local_index = RegisterToLocalIndex(the_register);
DCHECK(static_cast<size_t>(local_index) < environment_hints_.size());
environment_hints_[local_index] = hints;
} }
SerializerForBackgroundCompilation::SerializerForBackgroundCompilation( SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
JSHeapBroker* broker, Zone* zone, Handle<JSFunction> closure) JSHeapBroker* broker, Zone* zone, Handle<JSFunction> closure)
: broker_(broker), : broker_(broker),
zone_(zone), zone_(zone),
environment_(new (zone) Environment(zone, broker_->isolate(), closure)), environment_(new (zone) Environment(
closure_(closure), zone, broker_->isolate(),
bytecode_array_( closure->shared()->GetBytecodeArray()->register_count(),
handle(closure->shared()->GetBytecodeArray(), broker->isolate())) {} closure->shared()->GetBytecodeArray()->parameter_count())),
closure_(closure) {}
void SerializerForBackgroundCompilation::Run() { TraverseBytecode(); } SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
JSHeapBroker* broker, Zone* zone, Handle<JSFunction> closure,
const Hints& receiver, const HintsVector& arguments)
: broker_(broker),
zone_(zone),
environment_(new (zone) Environment(
this, broker->isolate(),
closure->shared()->GetBytecodeArray()->register_count(),
closure->shared()->GetBytecodeArray()->parameter_count(), receiver,
arguments)),
closure_(closure) {}
Hints SerializerForBackgroundCompilation::Run() {
JSFunctionRef closure_ref(broker(), closure_);
if (closure_ref.serialized_for_compilation()) {
return Hints(zone());
}
closure_ref.SetSerializedForCompilation();
FeedbackVectorRef fv(
broker(), handle(closure_->feedback_vector(), broker()->isolate()));
fv.SerializeSlots();
BytecodeArrayRef bytecode_array(
broker(),
handle(closure_->shared()->GetBytecodeArray(), broker()->isolate()));
closure_ref.Serialize();
TraverseBytecode();
return environment()->LookupReturnValue();
}
void SerializerForBackgroundCompilation::TraverseBytecode() { void SerializerForBackgroundCompilation::TraverseBytecode() {
interpreter::BytecodeArrayIterator bytecode_iterator(bytecode_array()); interpreter::BytecodeArrayIterator iterator(
handle(closure_->shared()->GetBytecodeArray(), broker()->isolate()));
for (; !bytecode_iterator.done(); bytecode_iterator.Advance()) { for (; !iterator.done(); iterator.Advance()) {
switch (bytecode_iterator.current_bytecode()) { switch (iterator.current_bytecode()) {
#define DEFINE_BYTECODE_CASE(name) \ #define DEFINE_BYTECODE_CASE(name) \
case interpreter::Bytecode::k##name: \ case interpreter::Bytecode::k##name: \
Visit##name(); \ Visit##name(&iterator); \
break; break;
SUPPORTED_BYTECODE_LIST(DEFINE_BYTECODE_CASE) SUPPORTED_BYTECODE_LIST(DEFINE_BYTECODE_CASE)
#undef DEFINE_BYTECODE_CASE #undef DEFINE_BYTECODE_CASE
default: default: {
environment()->Clear();
break; break;
}
} }
} }
} }
void SerializerForBackgroundCompilation::VisitIllegal() {} void SerializerForBackgroundCompilation::VisitIllegal(
interpreter::BytecodeArrayIterator* iterator) {
UNREACHABLE();
}
void SerializerForBackgroundCompilation::VisitWide(
interpreter::BytecodeArrayIterator* iterator) {
UNREACHABLE();
}
void SerializerForBackgroundCompilation::VisitExtraWide(
interpreter::BytecodeArrayIterator* iterator) {
UNREACHABLE();
}
void SerializerForBackgroundCompilation::VisitLdaUndefined(
interpreter::BytecodeArrayIterator* iterator) {
environment()->ReplaceAccumulatorHint(
broker()->isolate()->factory()->undefined_value());
}
void SerializerForBackgroundCompilation::VisitLdaNull(
interpreter::BytecodeArrayIterator* iterator) {
environment()->ReplaceAccumulatorHint(
broker()->isolate()->factory()->null_value());
}
void SerializerForBackgroundCompilation::VisitLdaZero(
interpreter::BytecodeArrayIterator* iterator) {
Handle<Object> zero(Smi::FromInt(0), broker()->isolate());
environment()->ReplaceAccumulatorHint(zero);
}
void SerializerForBackgroundCompilation::VisitLdaSmi(
interpreter::BytecodeArrayIterator* iterator) {
Handle<Object> smi(Smi::FromInt(iterator->GetImmediateOperand(0)),
broker()->isolate());
environment()->ReplaceAccumulatorHint(smi);
}
void SerializerForBackgroundCompilation::VisitLdaConstant(
interpreter::BytecodeArrayIterator* iterator) {
Handle<Object> constant(iterator->GetConstantForIndexOperand(0),
broker()->isolate());
environment()->ReplaceAccumulatorHint(constant);
}
void SerializerForBackgroundCompilation::VisitLdar(
interpreter::BytecodeArrayIterator* iterator) {
const Hints& hints =
environment()->LookupRegister(iterator->GetRegisterOperand(0));
environment()->SetAccumulatorHints(hints);
}
void SerializerForBackgroundCompilation::VisitStar(
interpreter::BytecodeArrayIterator* iterator) {
const Hints& hints = environment()->LookupAccumulator();
environment()->SetRegisterHints(iterator->GetRegisterOperand(0), hints);
}
void SerializerForBackgroundCompilation::VisitMov(
interpreter::BytecodeArrayIterator* iterator) {
const Hints& hints =
environment()->LookupRegister(iterator->GetRegisterOperand(0));
environment()->SetRegisterHints(iterator->GetRegisterOperand(1), hints);
}
void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver(
interpreter::BytecodeArrayIterator* iterator) {
ProcessCallVarArgs(iterator, ConvertReceiverMode::kNullOrUndefined);
}
void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver0(
interpreter::BytecodeArrayIterator* iterator) {
Hints receiver(zone());
receiver.push_back(broker()->isolate()->factory()->undefined_value());
const Hints& callee =
environment()->LookupRegister(iterator->GetRegisterOperand(0));
HintsVector parameters(zone());
ProcessCall(callee, receiver, parameters);
}
void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver1(
interpreter::BytecodeArrayIterator* iterator) {
Hints receiver(zone());
receiver.push_back(broker()->isolate()->factory()->undefined_value());
const Hints& callee =
environment()->LookupRegister(iterator->GetRegisterOperand(0));
const Hints& arg0 =
environment()->LookupRegister(iterator->GetRegisterOperand(1));
HintsVector parameters(zone());
parameters.push_back(arg0);
ProcessCall(callee, receiver, parameters);
}
void SerializerForBackgroundCompilation::VisitCallUndefinedReceiver2(
interpreter::BytecodeArrayIterator* iterator) {
Hints receiver(zone());
receiver.push_back(broker()->isolate()->factory()->undefined_value());
const Hints& callee =
environment()->LookupRegister(iterator->GetRegisterOperand(0));
const Hints& arg0 =
environment()->LookupRegister(iterator->GetRegisterOperand(1));
const Hints& arg1 =
environment()->LookupRegister(iterator->GetRegisterOperand(2));
HintsVector parameters(zone());
parameters.push_back(arg0);
parameters.push_back(arg1);
ProcessCall(callee, receiver, parameters);
}
void SerializerForBackgroundCompilation::VisitCallAnyReceiver(
interpreter::BytecodeArrayIterator* iterator) {
ProcessCallVarArgs(iterator, ConvertReceiverMode::kAny);
}
void SerializerForBackgroundCompilation::VisitCallNoFeedback(
interpreter::BytecodeArrayIterator* iterator) {
ProcessCallVarArgs(iterator, ConvertReceiverMode::kNullOrUndefined);
}
void SerializerForBackgroundCompilation::VisitCallProperty(
interpreter::BytecodeArrayIterator* iterator) {
ProcessCallVarArgs(iterator, ConvertReceiverMode::kNullOrUndefined);
}
void SerializerForBackgroundCompilation::VisitCallProperty0(
interpreter::BytecodeArrayIterator* iterator) {
const Hints& callee =
environment()->LookupRegister(iterator->GetRegisterOperand(0));
const Hints& receiver =
environment()->LookupRegister(iterator->GetRegisterOperand(1));
HintsVector parameters(zone());
ProcessCall(callee, receiver, parameters);
}
void SerializerForBackgroundCompilation::VisitCallProperty1(
interpreter::BytecodeArrayIterator* iterator) {
const Hints& callee =
environment()->LookupRegister(iterator->GetRegisterOperand(0));
const Hints& receiver =
environment()->LookupRegister(iterator->GetRegisterOperand(1));
const Hints& arg0 =
environment()->LookupRegister(iterator->GetRegisterOperand(2));
HintsVector parameters(zone());
parameters.push_back(arg0);
ProcessCall(callee, receiver, parameters);
}
void SerializerForBackgroundCompilation::VisitCallProperty2(
interpreter::BytecodeArrayIterator* iterator) {
const Hints& callee =
environment()->LookupRegister(iterator->GetRegisterOperand(0));
const Hints& receiver =
environment()->LookupRegister(iterator->GetRegisterOperand(1));
const Hints& arg0 =
environment()->LookupRegister(iterator->GetRegisterOperand(2));
const Hints& arg1 =
environment()->LookupRegister(iterator->GetRegisterOperand(3));
HintsVector parameters(zone());
parameters.push_back(arg0);
parameters.push_back(arg1);
ProcessCall(callee, receiver, parameters);
}
void SerializerForBackgroundCompilation::ProcessCall(
const Hints& callee, const Hints& receiver, const HintsVector& arguments) {
environment()->ClearAccumulatorHints();
for (auto value : callee) {
if (!value->IsJSFunction()) continue;
Handle<JSFunction> callee(Handle<JSFunction>::cast(value));
if (!callee->shared()->HasBytecodeArray() ||
!callee->shared()->IsInlineable())
continue;
SerializerForBackgroundCompilation child_serializer(
broker(), zone(), callee, receiver, arguments);
environment()->AddAccumulatorHints(child_serializer.Run());
}
}
void SerializerForBackgroundCompilation::ProcessCallVarArgs(
interpreter::BytecodeArrayIterator* iterator,
ConvertReceiverMode receiver_mode) {
const Hints& callee =
environment()->LookupRegister(iterator->GetRegisterOperand(0));
interpreter::Register first_reg = iterator->GetRegisterOperand(1);
size_t reg_count = iterator->GetRegisterCountOperand(2);
Hints receiver(zone());
interpreter::Register first_arg;
int arg_count;
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
// The receiver is implicit (and undefined), the arguments are in
// consecutive registers.
arg_count = static_cast<int>(reg_count);
receiver.push_back(broker()->isolate()->factory()->undefined_value());
first_arg = first_reg;
} else {
// The receiver is the first register, followed by the arguments in the
// consecutive registers.
arg_count = static_cast<int>(reg_count) - 1;
receiver = environment()->LookupRegister(first_reg);
first_arg = interpreter::Register(first_reg.index() + 1);
}
HintsVector arguments(zone());
// The function arguments are in consecutive registers.
int arg_base = first_arg.index();
for (int i = 0; i < arg_count; ++i) {
arguments.push_back(
environment()->LookupRegister(interpreter::Register(arg_base + i)));
}
ProcessCall(callee, receiver, arguments);
}
void SerializerForBackgroundCompilation::VisitReturn(
interpreter::BytecodeArrayIterator* iterator) {
environment()->AddReturnValueHints(environment()->LookupAccumulator());
environment()->Clear();
}
#define DEFINE_SKIPPED_JUMP(name, ...) \
void SerializerForBackgroundCompilation::Visit##name( \
interpreter::BytecodeArrayIterator* iterator) { \
environment()->Clear(); \
}
CLEAR_ENVIRONMENT_LIST(DEFINE_SKIPPED_JUMP)
#undef DEFINE_SKIPPED_JUMP
#define DEFINE_CLEAR_ACCUMULATOR(name, ...) \
void SerializerForBackgroundCompilation::Visit##name( \
interpreter::BytecodeArrayIterator* iterator) { \
environment()->ClearAccumulatorHints(); \
}
CLEAR_ACCUMULATOR_LIST(DEFINE_CLEAR_ACCUMULATOR)
#undef DEFINE_CLEAR_ACCUMULATOR
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
......
...@@ -6,60 +6,148 @@ ...@@ -6,60 +6,148 @@
#define V8_COMPILER_SERIALIZER_FOR_BACKGROUND_COMPILATION_H_ #define V8_COMPILER_SERIALIZER_FOR_BACKGROUND_COMPILATION_H_
#include "src/handles.h" #include "src/handles.h"
#include "src/zone/zone-containers.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace interpreter { namespace interpreter {
class BytecodeArrayIterator; class BytecodeArrayIterator;
} class Register;
} // namespace interpreter
class BytecodeArray;
class FeedbackVector; class FeedbackVector;
class LookupIterator;
class NativeContext;
class ScriptContextTable;
class SharedFunctionInfo; class SharedFunctionInfo;
class BytecodeArray;
class SourcePositionTableIterator; class SourcePositionTableIterator;
class Zone; class Zone;
namespace compiler { namespace compiler {
#define SUPPORTED_BYTECODE_LIST(V) V(Illegal) #define CLEAR_ENVIRONMENT_LIST(V) \
V(Abort) \
V(CallRuntime) \
V(CallRuntimeForPair) \
V(CreateBlockContext) \
V(CreateFunctionContext) \
V(CreateEvalContext) \
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(ReThrow) \
V(StaContextSlot) \
V(StaCurrentContextSlot) \
V(Throw)
#define CLEAR_ACCUMULATOR_LIST(V) \
V(Construct) \
V(CreateClosure) \
V(CreateEmptyObjectLiteral) \
V(CreateMappedArguments) \
V(CreateRestParameter) \
V(CreateUnmappedArguments) \
V(LdaContextSlot) \
V(LdaCurrentContextSlot) \
V(LdaGlobal) \
V(LdaGlobalInsideTypeof) \
V(LdaImmutableContextSlot) \
V(LdaImmutableCurrentContextSlot) \
V(LdaKeyedProperty) \
V(LdaNamedProperty) \
V(LdaNamedPropertyNoFeedback)
#define SUPPORTED_BYTECODE_LIST(V) \
V(CallAnyReceiver) \
V(CallNoFeedback) \
V(CallProperty) \
V(CallProperty0) \
V(CallProperty1) \
V(CallProperty2) \
V(CallUndefinedReceiver) \
V(CallUndefinedReceiver0) \
V(CallUndefinedReceiver1) \
V(CallUndefinedReceiver2) \
V(ExtraWide) \
V(Illegal) \
V(LdaConstant) \
V(LdaNull) \
V(Ldar) \
V(LdaSmi) \
V(LdaUndefined) \
V(LdaZero) \
V(Mov) \
V(Return) \
V(Star) \
V(Wide) \
CLEAR_ENVIRONMENT_LIST(V) \
CLEAR_ACCUMULATOR_LIST(V)
class JSHeapBroker; class JSHeapBroker;
typedef ZoneVector<Handle<Object>> Hints;
typedef ZoneVector<Hints> HintsVector;
// The SerializerForBackgroundCompilation makes sure that the relevant function // The SerializerForBackgroundCompilation makes sure that the relevant function
// data such as bytecode, SharedFunctionInfo and FeedbackVector, used by later // data such as bytecode, SharedFunctionInfo and FeedbackVector, used by later
// optimizations in the compiler, is copied to the heap broker. // optimizations in the compiler, is copied to the heap broker.
class SerializerForBackgroundCompilation { class SerializerForBackgroundCompilation {
public: public:
explicit SerializerForBackgroundCompilation(JSHeapBroker* broker, Zone* zone, class Environment;
Handle<JSFunction> closure);
void Run(); SerializerForBackgroundCompilation(JSHeapBroker* broker, Zone* zone,
Handle<JSFunction> closure);
SerializerForBackgroundCompilation(JSHeapBroker* broker, Zone* zone,
Handle<JSFunction> closure,
const Hints& receiver,
const HintsVector& arguments);
Zone* zone() const { return zone_; } Hints Run();
const Handle<BytecodeArray>& bytecode_array() const { Zone* zone() const { return zone_; }
return bytecode_array_;
}
private: private:
class Environment;
void TraverseBytecode(); void TraverseBytecode();
#define DECLARE_VISIT_BYTECODE(name, ...) void Visit##name(); #define DECLARE_VISIT_BYTECODE(name, ...) \
void Visit##name(interpreter::BytecodeArrayIterator* iterator);
SUPPORTED_BYTECODE_LIST(DECLARE_VISIT_BYTECODE) SUPPORTED_BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
#undef DECLARE_VISIT_BYTECODE #undef DECLARE_VISIT_BYTECODE
JSHeapBroker* broker() { return broker_; } JSHeapBroker* broker() const { return broker_; }
Environment* environment() { return environment_; } Environment* environment() const { return environment_; }
void ProcessCall(const Hints& callee, const Hints& receiver,
const HintsVector& arguments);
void ProcessCallVarArgs(interpreter::BytecodeArrayIterator* iterator,
ConvertReceiverMode receiver_mode);
JSHeapBroker* broker_; JSHeapBroker* broker_;
Zone* zone_; Zone* zone_;
Environment* environment_; Environment* environment_;
Handle<JSFunction> closure_; Handle<JSFunction> closure_;
Handle<BytecodeArray> bytecode_array_;
}; };
} // namespace compiler } // namespace compiler
......
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