Commit ecf2e1cf authored by Mike Stanton's avatar Mike Stanton Committed by Commit Bot

[Turbofan] Brokerize tagged templates in the bytecode graph builder

The bytecode graph builder currently creates the tagged template if
it hasn't yet been done. This CL moves that work to serialization time.

Bug: v8:7790
Change-Id: I9571c5ad2f553584869056fb0cf501e03563d6f0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1687670
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62681}
parent 83cb73f3
......@@ -35,8 +35,8 @@ class BytecodeGraphBuilder {
BytecodeGraphBuilder(JSHeapBroker* broker, Zone* local_zone,
BytecodeArrayRef bytecode_array,
Handle<SharedFunctionInfo> shared,
Handle<FeedbackVector> feedback_vector,
BailoutId osr_offset, JSGraph* jsgraph,
FeedbackVectorRef feedback_vector, BailoutId osr_offset,
JSGraph* jsgraph,
CallFrequency const& invocation_frequency,
SourcePositionTable* source_positions,
Handle<NativeContext> native_context, int inlining_id,
......@@ -320,9 +320,7 @@ class BytecodeGraphBuilder {
}
Zone* local_zone() const { return local_zone_; }
const BytecodeArrayRef bytecode_array() const { return bytecode_array_; }
const Handle<FeedbackVector>& feedback_vector() const {
return feedback_vector_;
}
FeedbackVectorRef feedback_vector() const { return feedback_vector_; }
const JSTypeHintLowering& type_hint_lowering() const {
return type_hint_lowering_;
}
......@@ -382,7 +380,7 @@ class BytecodeGraphBuilder {
JSGraph* const jsgraph_;
CallFrequency const invocation_frequency_;
BytecodeArrayRef const bytecode_array_;
Handle<FeedbackVector> const feedback_vector_;
FeedbackVectorRef feedback_vector_;
JSTypeHintLowering const type_hint_lowering_;
const FrameStateFunctionInfo* const frame_state_function_info_;
std::unique_ptr<SourcePositionTableIterator> source_position_iterator_;
......@@ -938,9 +936,9 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint(
BytecodeGraphBuilder::BytecodeGraphBuilder(
JSHeapBroker* broker, Zone* local_zone, BytecodeArrayRef bytecode_array,
Handle<SharedFunctionInfo> shared_info,
Handle<FeedbackVector> feedback_vector, BailoutId osr_offset,
JSGraph* jsgraph, CallFrequency const& invocation_frequency,
Handle<SharedFunctionInfo> shared_info, FeedbackVectorRef feedback_vector,
BailoutId osr_offset, JSGraph* jsgraph,
CallFrequency const& invocation_frequency,
SourcePositionTable* source_positions, Handle<NativeContext> native_context,
int inlining_id, BytecodeGraphBuilderFlags flags)
: broker_(broker),
......@@ -950,7 +948,7 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
bytecode_array_(bytecode_array),
feedback_vector_(feedback_vector),
type_hint_lowering_(
jsgraph, feedback_vector,
jsgraph, feedback_vector.object(),
(flags & BytecodeGraphBuilderFlag::kBailoutOnUninitialized)
? JSTypeHintLowering::kBailoutOnUninitialized
: JSTypeHintLowering::kNoFlags),
......@@ -1014,8 +1012,8 @@ Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
FeedbackSlot slot = FeedbackVector::ToSlot(slot_id);
FeedbackNexus nexus(feedback_vector(), slot);
return VectorSlotPair(feedback_vector(), slot, nexus.ic_state());
FeedbackNexus nexus(feedback_vector().object(), slot);
return VectorSlotPair(feedback_vector().object(), slot, nexus.ic_state());
}
void BytecodeGraphBuilder::CreateGraph() {
......@@ -1390,7 +1388,8 @@ Node* BytecodeGraphBuilder::BuildLoadGlobal(Handle<Name> name,
uint32_t feedback_slot_index,
TypeofMode typeof_mode) {
VectorSlotPair feedback = CreateVectorSlotPair(feedback_slot_index);
DCHECK(IsLoadGlobalICKind(feedback_vector()->GetKind(feedback.slot())));
DCHECK(
IsLoadGlobalICKind(feedback_vector().object()->GetKind(feedback.slot())));
const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
return NewNode(op);
}
......@@ -1917,7 +1916,7 @@ void BytecodeGraphBuilder::VisitCreateClosure() {
: AllocationType::kYoung;
const Operator* op = javascript()->CreateClosure(
shared_info,
feedback_vector()->GetClosureFeedbackCell(
feedback_vector().object()->GetClosureFeedbackCell(
bytecode_iterator().GetIndexOperand(1)),
handle(jsgraph()->isolate()->builtins()->builtin(Builtins::kCompileLazy),
isolate()),
......@@ -2078,32 +2077,14 @@ void BytecodeGraphBuilder::VisitCloneObject() {
}
void BytecodeGraphBuilder::VisitGetTemplateObject() {
Handle<TemplateObjectDescription> description =
Handle<TemplateObjectDescription>::cast(
bytecode_iterator().GetConstantForIndexOperand(0, isolate()));
DisallowHeapAccessIf no_heap_access(FLAG_concurrent_inlining);
FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
FeedbackNexus nexus(feedback_vector(), slot);
Handle<JSArray> cached_value;
if (nexus.GetFeedback() == MaybeObject::FromSmi(Smi::zero())) {
// It's not observable when the template object is created, so we
// can just create it eagerly during graph building and bake in
// the JSArray constant here.
//
// It simplifies the compiler interface if we don't set this value
// in the feedback vector, especially as we consider concurrent
// compilation. We can count on the {cached_value} to be re-created
// later by bytecode if necessary.
cached_value = TemplateObjectDescription::GetTemplateObject(
isolate(), native_context(), description, shared_info(), slot.ToInt());
} else {
cached_value =
handle(JSArray::cast(nexus.GetFeedback()->GetHeapObjectAssumeStrong()),
isolate());
}
Node* template_object = jsgraph()->HeapConstant(cached_value);
environment()->BindAccumulator(template_object);
ObjectRef description(
broker(), bytecode_iterator().GetConstantForIndexOperand(0, isolate()));
SharedFunctionInfoRef shared(broker(), shared_info());
JSArrayRef template_object =
shared.GetTemplateObject(description, feedback_vector(), slot);
environment()->BindAccumulator(jsgraph()->Constant(template_object));
}
Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegisters(
......@@ -2657,7 +2638,7 @@ void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) {
BinaryOperationHint BytecodeGraphBuilder::GetBinaryOperationHint(
int operand_index) {
FeedbackSlot slot = bytecode_iterator().GetSlotOperand(operand_index);
FeedbackNexus nexus(feedback_vector(), slot);
FeedbackNexus nexus(feedback_vector().object(), slot);
return nexus.GetBinaryOperationFeedback();
}
......@@ -2665,14 +2646,14 @@ BinaryOperationHint BytecodeGraphBuilder::GetBinaryOperationHint(
// feedback.
CompareOperationHint BytecodeGraphBuilder::GetCompareOperationHint() {
FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
FeedbackNexus nexus(feedback_vector(), slot);
FeedbackNexus nexus(feedback_vector().object(), slot);
return nexus.GetCompareOperationFeedback();
}
// Helper function to create for-in mode from the recorded type feedback.
ForInMode BytecodeGraphBuilder::GetForInMode(int operand_index) {
FeedbackSlot slot = bytecode_iterator().GetSlotOperand(operand_index);
FeedbackNexus nexus(feedback_vector(), slot);
FeedbackNexus nexus(feedback_vector().object(), slot);
switch (nexus.GetForInFeedback()) {
case ForInHint::kNone:
case ForInHint::kEnumCacheKeysAndIndices:
......@@ -2687,7 +2668,8 @@ ForInMode BytecodeGraphBuilder::GetForInMode(int operand_index) {
CallFrequency BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const {
if (invocation_frequency_.IsUnknown()) return CallFrequency();
FeedbackNexus nexus(feedback_vector(), FeedbackVector::ToSlot(slot_id));
FeedbackNexus nexus(feedback_vector().object(),
FeedbackVector::ToSlot(slot_id));
float feedback_frequency = nexus.ComputeCallFrequency();
if (feedback_frequency == 0.0f) {
// This is to prevent multiplying zero and infinity.
......@@ -2698,7 +2680,8 @@ CallFrequency BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const {
}
SpeculationMode BytecodeGraphBuilder::GetSpeculationMode(int slot_id) const {
FeedbackNexus nexus(feedback_vector(), FeedbackVector::ToSlot(slot_id));
FeedbackNexus nexus(feedback_vector().object(),
FeedbackVector::ToSlot(slot_id));
return nexus.GetSpeculationMode();
}
......@@ -4041,8 +4024,9 @@ void BuildGraphFromBytecode(JSHeapBroker* broker, Zone* local_zone,
int inlining_id, BytecodeGraphBuilderFlags flags) {
BytecodeArrayRef bytecode_array_ref(broker, bytecode_array);
DCHECK(bytecode_array_ref.IsSerializedForCompilation());
FeedbackVectorRef feedback_vector_ref(broker, feedback_vector);
BytecodeGraphBuilder builder(broker, local_zone, bytecode_array_ref, shared,
feedback_vector, osr_offset, jsgraph,
feedback_vector_ref, osr_offset, jsgraph,
invocation_frequency, source_positions,
native_context, inlining_id, flags);
builder.CreateGraph();
......
......@@ -689,6 +689,12 @@ class V8_EXPORT_PRIVATE SharedFunctionInfoRef : public HeapObjectRef {
bool IsSerializedForCompilation(FeedbackVectorRef feedback) const;
void SetSerializedForCompilation(FeedbackVectorRef feedback);
// Template objects may not be created at compilation time. This method
// wraps the retrieval of the template object and creates it if
// necessary.
JSArrayRef GetTemplateObject(ObjectRef description, FeedbackVectorRef vector,
FeedbackSlot slot, bool serialize = false);
void SerializeFunctionTemplateInfo();
base::Optional<FunctionTemplateInfoRef> function_template_info() const;
};
......
......@@ -27,6 +27,7 @@
#include "src/objects/js-regexp-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/template-objects-inl.h"
#include "src/objects/templates.h"
#include "src/utils/boxed-float.h"
#include "src/utils/utils.h"
......@@ -1513,6 +1514,18 @@ class SharedFunctionInfoData : public HeapObjectData {
FunctionTemplateInfoData* function_template_info() const {
return function_template_info_;
}
JSArrayData* GetTemplateObject(FeedbackSlot slot) const {
auto lookup_it = template_objects_.find(slot.ToInt());
if (lookup_it != template_objects_.cend()) {
return lookup_it->second;
}
return nullptr;
}
void SetTemplateObject(FeedbackSlot slot, JSArrayData* object) {
CHECK(
template_objects_.insert(std::make_pair(slot.ToInt(), object)).second);
}
#define DECL_ACCESSOR(type, name) \
type name() const { return name##_; }
BROKER_SFI_FIELDS(DECL_ACCESSOR)
......@@ -1528,6 +1541,7 @@ class SharedFunctionInfoData : public HeapObjectData {
BROKER_SFI_FIELDS(DECL_MEMBER)
#undef DECL_MEMBER
FunctionTemplateInfoData* function_template_info_;
ZoneMap<int, JSArrayData*> template_objects_;
};
SharedFunctionInfoData::SharedFunctionInfoData(
......@@ -1546,7 +1560,8 @@ SharedFunctionInfoData::SharedFunctionInfoData(
BROKER_SFI_FIELDS(INIT_MEMBER)
#undef INIT_MEMBER
,
function_template_info_(nullptr) {
function_template_info_(nullptr),
template_objects_(broker->zone()) {
DCHECK_EQ(HasBuiltinId_, builtin_id_ != Builtins::kNoBuiltinId);
DCHECK_EQ(HasBytecodeArray_, GetBytecodeArray_ != nullptr);
}
......@@ -3531,6 +3546,46 @@ bool JSFunctionRef::IsSerializedForCompilation() const {
shared().IsSerializedForCompilation(feedback_vector());
}
JSArrayRef SharedFunctionInfoRef::GetTemplateObject(ObjectRef description,
FeedbackVectorRef vector,
FeedbackSlot slot,
bool serialize) {
// Look in the feedback vector for the array. A Smi indicates that it's
// not yet cached here.
ObjectRef candidate = vector.get(slot);
if (!candidate.IsSmi()) {
return candidate.AsJSArray();
}
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
Handle<TemplateObjectDescription> tod =
Handle<TemplateObjectDescription>::cast(description.object());
Handle<JSArray> template_object =
TemplateObjectDescription::GetTemplateObject(
broker()->isolate(), broker()->native_context().object(), tod,
object(), slot.ToInt());
return JSArrayRef(broker(), template_object);
}
JSArrayData* array = data()->AsSharedFunctionInfo()->GetTemplateObject(slot);
if (array != nullptr) return JSArrayRef(broker(), array);
CHECK(serialize);
CHECK(broker()->SerializingAllowed());
Handle<TemplateObjectDescription> tod =
Handle<TemplateObjectDescription>::cast(description.object());
Handle<JSArray> template_object =
TemplateObjectDescription::GetTemplateObject(
broker()->isolate(), broker()->native_context().object(), tod,
object(), slot.ToInt());
array = broker()->GetOrCreateData(template_object)->AsJSArray();
data()->AsSharedFunctionInfo()->SetTemplateObject(slot, array);
return JSArrayRef(broker(), array);
}
void SharedFunctionInfoRef::SetSerializedForCompilation(
FeedbackVectorRef feedback) {
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
......
......@@ -538,6 +538,20 @@ void SerializerForBackgroundCompilation::VisitGetSuperConstructor(
}
}
void SerializerForBackgroundCompilation::VisitGetTemplateObject(
BytecodeArrayIterator* iterator) {
ObjectRef description(
broker(), iterator->GetConstantForIndexOperand(0, broker()->isolate()));
FeedbackSlot slot = iterator->GetSlotOperand(1);
FeedbackVectorRef feedback_vector(
broker(), environment()->function().feedback_vector());
SharedFunctionInfoRef shared(broker(), environment()->function().shared());
JSArrayRef template_object =
shared.GetTemplateObject(description, feedback_vector, slot, true);
environment()->accumulator_hints().Clear();
environment()->accumulator_hints().AddConstant(template_object.object());
}
void SerializerForBackgroundCompilation::VisitLdaTrue(
BytecodeArrayIterator* iterator) {
environment()->accumulator_hints().Clear();
......
......@@ -74,7 +74,6 @@ namespace compiler {
V(ForInEnumerate) \
V(ForInNext) \
V(ForInStep) \
V(GetTemplateObject) \
V(Inc) \
V(LdaLookupSlot) \
V(LdaLookupSlotInsideTypeof) \
......@@ -174,6 +173,7 @@ namespace compiler {
V(CreateFunctionContext) \
V(CreateWithContext) \
V(GetSuperConstructor) \
V(GetTemplateObject) \
V(InvokeIntrinsic) \
V(LdaConstant) \
V(LdaContextSlot) \
......
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