Commit cfcb3597 authored by ishell's avatar ishell Committed by Commit bot

[ic] Let LoadGlobalIC load the variable name from TypeFeedbackMetadata.

This simplifies the calling convention of LoadGlobalIC.

Currently we do a linear search to get the name but I'll address this in a follow-up CL.

BUG=chromium:576312
TBR=rossberg@chromium.org

Review-Url: https://codereview.chromium.org/2084913006
Cr-Commit-Position: refs/heads/master@{#37253}
parent a7a9ac37
......@@ -134,7 +134,7 @@ void VariableProxy::AssignFeedbackVectorSlots(Isolate* isolate,
static_cast<int>(reinterpret_cast<intptr_t>(entry->value)));
return;
}
variable_feedback_slot_ = spec->AddLoadGlobalICSlot();
variable_feedback_slot_ = spec->AddLoadGlobalICSlot(var()->name());
cache->Put(var(), variable_feedback_slot_);
} else {
variable_feedback_slot_ = spec->AddLoadICSlot();
......
......@@ -5487,12 +5487,11 @@ void Generate_LoadIC_Miss(CodeStubAssembler* assembler) {
void Generate_LoadGlobalIC_Miss(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* name = assembler->Parameter(0);
Node* slot = assembler->Parameter(1);
Node* vector = assembler->Parameter(2);
Node* context = assembler->Parameter(3);
Node* slot = assembler->Parameter(0);
Node* vector = assembler->Parameter(1);
Node* context = assembler->Parameter(2);
assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, name, slot,
assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot,
vector);
}
......@@ -5519,23 +5518,23 @@ void Generate_LoadIC_Slow(CodeStubAssembler* assembler) {
void Generate_LoadGlobalIC_SlowInsideTypeof(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* name = assembler->Parameter(0);
// Node* slot = assembler->Parameter(1);
// Node* vector = assembler->Parameter(2);
Node* context = assembler->Parameter(3);
Node* slot = assembler->Parameter(0);
Node* vector = assembler->Parameter(1);
Node* context = assembler->Parameter(2);
assembler->TailCallRuntime(Runtime::kGetGlobalInsideTypeof, context, name);
assembler->TailCallRuntime(Runtime::kGetGlobalInsideTypeof, context, slot,
vector);
}
void Generate_LoadGlobalIC_SlowNotInsideTypeof(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* name = assembler->Parameter(0);
// Node* slot = assembler->Parameter(1);
// Node* vector = assembler->Parameter(2);
Node* context = assembler->Parameter(3);
Node* slot = assembler->Parameter(0);
Node* vector = assembler->Parameter(1);
Node* context = assembler->Parameter(2);
assembler->TailCallRuntime(Runtime::kGetGlobalNotInsideTypeof, context, name);
assembler->TailCallRuntime(Runtime::kGetGlobalNotInsideTypeof, context, slot,
vector);
}
void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
......
......@@ -2350,12 +2350,13 @@ void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) {
Node* native_context = LoadNativeContext(p->context);
Node* receiver = LoadFixedArrayElement(
native_context, Int32Constant(Context::EXTENSION_INDEX));
TailCallStub(descriptor, handler, p->context, receiver, p->name, p->slot,
Node* fake_name = IntPtrConstant(0);
TailCallStub(descriptor, handler, p->context, receiver, fake_name, p->slot,
p->vector);
}
Bind(&miss);
{
TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, p->slot,
TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->slot,
p->vector);
}
}
......
......@@ -448,24 +448,24 @@ void LoadGlobalICTrampolineStub::GenerateAssembly(
CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
Node* name = assembler->Parameter(0);
Node* slot = assembler->Parameter(1);
Node* context = assembler->Parameter(2);
Node* slot = assembler->Parameter(0);
Node* context = assembler->Parameter(1);
Node* vector = assembler->LoadTypeFeedbackVectorForStub();
CodeStubAssembler::LoadICParameters p(context, nullptr, name, slot, vector);
CodeStubAssembler::LoadICParameters p(context, nullptr, nullptr, slot,
vector);
assembler->LoadGlobalIC(&p);
}
void LoadGlobalICStub::GenerateAssembly(CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
Node* name = assembler->Parameter(0);
Node* slot = assembler->Parameter(1);
Node* vector = assembler->Parameter(2);
Node* context = assembler->Parameter(3);
Node* slot = assembler->Parameter(0);
Node* vector = assembler->Parameter(1);
Node* context = assembler->Parameter(2);
CodeStubAssembler::LoadICParameters p(context, nullptr, name, slot, vector);
CodeStubAssembler::LoadICParameters p(context, nullptr, nullptr, slot,
vector);
assembler->LoadGlobalIC(&p);
}
......
......@@ -2262,7 +2262,6 @@ RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
HandleScope scope(isolate);
Handle<Object> receiver = args.at<Object>(0);
Handle<Name> key = args.at<Name>(1);
DCHECK_EQ(4, args.length());
Handle<Smi> slot = args.at<Smi>(2);
......@@ -2273,12 +2272,15 @@ RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
// set up outside the IC, handle that here.
FeedbackVectorSlotKind kind = vector->GetKind(vector_slot);
if (kind == FeedbackVectorSlotKind::LOAD_IC) {
Handle<Name> key = args.at<Name>(1);
LoadICNexus nexus(vector, vector_slot);
LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
ic.UpdateState(receiver, key);
RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
} else if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) {
Handle<Name> key(vector->GetName(vector_slot), isolate);
DCHECK_NE(*key, *isolate->factory()->empty_string());
DCHECK_EQ(*isolate->global_object(), *receiver);
LoadGlobalICNexus nexus(vector, vector_slot);
LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
......@@ -2286,6 +2288,7 @@ RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
RETURN_RESULT_OR_FAILURE(isolate, ic.Load(key));
} else {
Handle<Name> key = args.at<Name>(1);
DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, kind);
KeyedLoadICNexus nexus(vector, vector_slot);
KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
......@@ -2298,14 +2301,15 @@ RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
DCHECK_EQ(2, args.length());
Handle<JSGlobalObject> global = isolate->global_object();
Handle<Name> name = args.at<Name>(0);
Handle<Smi> slot = args.at<Smi>(1);
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
Handle<Smi> slot = args.at<Smi>(0);
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
vector->GetKind(vector_slot));
Handle<String> name(vector->GetName(vector_slot), isolate);
DCHECK_NE(*name, *isolate->factory()->empty_string());
LoadGlobalICNexus nexus(vector, vector_slot);
LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
......
......@@ -101,16 +101,14 @@ FunctionType* LoadGlobalDescriptor::BuildCallInterfaceDescriptorFunctionType(
Isolate* isolate, int paramater_count) {
Zone* zone = isolate->interface_descriptor_zone();
FunctionType* function =
Type::Function(AnyTagged(zone), Type::Undefined(), 2, zone)->AsFunction();
function->InitParameter(0, AnyTagged(zone));
function->InitParameter(1, SmiType(zone));
Type::Function(AnyTagged(zone), Type::Undefined(), 1, zone)->AsFunction();
function->InitParameter(0, SmiType(zone));
return function;
}
void LoadGlobalDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {LoadWithVectorDescriptor::NameRegister(),
LoadWithVectorDescriptor::SlotRegister()};
Register registers[] = {LoadWithVectorDescriptor::SlotRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
......@@ -119,17 +117,15 @@ LoadGlobalWithVectorDescriptor::BuildCallInterfaceDescriptorFunctionType(
Isolate* isolate, int paramater_count) {
Zone* zone = isolate->interface_descriptor_zone();
FunctionType* function =
Type::Function(AnyTagged(zone), Type::Undefined(), 3, zone)->AsFunction();
function->InitParameter(0, AnyTagged(zone));
function->InitParameter(1, SmiType(zone));
function->InitParameter(2, AnyTagged(zone));
Type::Function(AnyTagged(zone), Type::Undefined(), 2, zone)->AsFunction();
function->InitParameter(0, SmiType(zone));
function->InitParameter(1, AnyTagged(zone));
return function;
}
void LoadGlobalWithVectorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {LoadWithVectorDescriptor::NameRegister(),
LoadWithVectorDescriptor::SlotRegister(),
Register registers[] = {LoadWithVectorDescriptor::SlotRegister(),
LoadWithVectorDescriptor::VectorRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
......
......@@ -374,7 +374,7 @@ class LoadGlobalDescriptor : public CallInterfaceDescriptor {
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadGlobalDescriptor,
CallInterfaceDescriptor)
enum ParameterIndices { kNameIndex, kSlotIndex };
enum ParameterIndices { kSlotIndex };
};
class LoadGlobalWithVectorDescriptor : public CallInterfaceDescriptor {
......@@ -382,7 +382,7 @@ class LoadGlobalWithVectorDescriptor : public CallInterfaceDescriptor {
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadGlobalWithVectorDescriptor,
CallInterfaceDescriptor)
enum ParameterIndices { kNameIndex, kSlotIndex, kVectorIndex };
enum ParameterIndices { kSlotIndex, kVectorIndex };
};
class StoreDescriptor : public CallInterfaceDescriptor {
......
......@@ -578,6 +578,40 @@ void TransitionArray::TransitionArrayPrint(std::ostream& os) { // NOLINT
os << "\n";
}
template void FeedbackVectorSpecBase<StaticFeedbackVectorSpec>::Print();
template void FeedbackVectorSpecBase<FeedbackVectorSpec>::Print();
template <typename Derived>
void FeedbackVectorSpecBase<Derived>::Print() {
OFStream os(stdout);
FeedbackVectorSpecPrint(os);
os << std::flush;
}
template <typename Derived>
void FeedbackVectorSpecBase<Derived>::FeedbackVectorSpecPrint(
std::ostream& os) { // NOLINT
int slot_count = This()->slots();
os << " - slot_count: " << slot_count;
if (slot_count == 0) {
os << " (empty)\n";
return;
}
for (int slot = 0, name_index = 0; slot < slot_count;) {
FeedbackVectorSlotKind kind = This()->GetKind(slot);
int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
DCHECK_LT(0, entry_size);
os << "\n Slot #" << slot << " " << kind;
if (TypeFeedbackMetadata::SlotRequiresName(kind)) {
os << ", " << Brief(*This()->GetName(name_index++));
}
slot += entry_size;
}
os << "\n";
}
void TypeFeedbackMetadata::Print() {
OFStream os(stdout);
......@@ -594,12 +628,16 @@ void TypeFeedbackMetadata::TypeFeedbackMetadataPrint(
os << " (empty)\n";
return;
}
os << "\n - slot_count: " << slot_count();
TypeFeedbackMetadataIterator iter(this);
while (iter.HasNext()) {
FeedbackVectorSlot slot = iter.Next();
FeedbackVectorSlotKind kind = iter.kind();
os << "\n Slot " << slot << " " << kind;
if (TypeFeedbackMetadata::SlotRequiresName(kind)) {
os << ", " << Brief(iter.name());
}
}
os << "\n";
}
......@@ -625,7 +663,11 @@ void TypeFeedbackVector::TypeFeedbackVectorPrint(std::ostream& os) { // NOLINT
FeedbackVectorSlot slot = iter.Next();
FeedbackVectorSlotKind kind = iter.kind();
os << "\n Slot " << slot << " " << kind << " ";
os << "\n Slot " << slot << " " << kind;
if (TypeFeedbackMetadata::SlotRequiresName(kind)) {
os << ", " << Brief(iter.name());
}
os << " ";
switch (kind) {
case FeedbackVectorSlotKind::LOAD_IC: {
LoadICNexus nexus(this, slot);
......
......@@ -350,8 +350,14 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
namespace {
Object* GetGlobal(Isolate* isolate, Handle<String> name,
Object* GetGlobal(Isolate* isolate, int slot, Handle<TypeFeedbackVector> vector,
bool should_throw_reference_error) {
FeedbackVectorSlot vector_slot = vector->ToSlot(slot);
DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
vector->GetKind(vector_slot));
Handle<String> name(vector->GetName(vector_slot), isolate);
DCHECK_NE(*name, *isolate->factory()->empty_string());
Handle<JSGlobalObject> global = isolate->global_object();
Handle<ScriptContextTable> script_contexts(
......@@ -382,16 +388,18 @@ Object* GetGlobal(Isolate* isolate, Handle<String> name,
RUNTIME_FUNCTION(Runtime_GetGlobalInsideTypeof) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
return GetGlobal(isolate, name, false);
DCHECK_EQ(2, args.length());
CONVERT_SMI_ARG_CHECKED(slot, 0);
CONVERT_ARG_HANDLE_CHECKED(TypeFeedbackVector, vector, 1);
return GetGlobal(isolate, slot, vector, false);
}
RUNTIME_FUNCTION(Runtime_GetGlobalNotInsideTypeof) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
return GetGlobal(isolate, name, true);
DCHECK_EQ(2, args.length());
CONVERT_SMI_ARG_CHECKED(slot, 0);
CONVERT_ARG_HANDLE_CHECKED(TypeFeedbackVector, vector, 1);
return GetGlobal(isolate, slot, vector, true);
}
// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
......
......@@ -384,8 +384,8 @@ namespace internal {
F(SetPrototype, 2, 1) \
F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
F(GetProperty, 2, 1) \
F(GetGlobalInsideTypeof, 1, 1) \
F(GetGlobalNotInsideTypeof, 1, 1) \
F(GetGlobalInsideTypeof, 2, 1) \
F(GetGlobalNotInsideTypeof, 2, 1) \
F(KeyedGetProperty, 2, 1) \
F(StoreGlobalViaContext_Sloppy, 2, 1) \
F(StoreGlobalViaContext_Strict, 2, 1) \
......@@ -953,7 +953,7 @@ namespace internal {
F(KeyedStoreIC_MissFromStubFailure, 5, 1) \
F(KeyedStoreIC_Slow, 5, 1) \
F(LoadElementWithInterceptor, 2, 1) \
F(LoadGlobalIC_Miss, 3, 1) \
F(LoadGlobalIC_Miss, 2, 1) \
F(LoadIC_Miss, 4, 1) \
F(LoadIC_MissFromStubFailure, 4, 1) \
F(LoadPropertyWithInterceptor, 3, 1) \
......
......@@ -14,13 +14,11 @@ namespace internal {
template <typename Derived>
FeedbackVectorSlot FeedbackVectorSpecBase<Derived>::AddSlot(
FeedbackVectorSlotKind kind) {
Derived* derived = static_cast<Derived*>(this);
int slot = derived->slots();
int slot = This()->slots();
int entries_per_slot = TypeFeedbackMetadata::GetSlotSize(kind);
derived->append(kind);
This()->append(kind);
for (int i = 1; i < entries_per_slot; i++) {
derived->append(FeedbackVectorSlotKind::INVALID);
This()->append(FeedbackVectorSlotKind::INVALID);
}
return FeedbackVectorSlot(slot);
}
......@@ -57,6 +55,26 @@ int TypeFeedbackMetadata::GetSlotSize(FeedbackVectorSlotKind kind) {
return kind == FeedbackVectorSlotKind::GENERAL ? 1 : 2;
}
bool TypeFeedbackMetadata::SlotRequiresName(FeedbackVectorSlotKind kind) {
switch (kind) {
case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
return true;
case FeedbackVectorSlotKind::CALL_IC:
case FeedbackVectorSlotKind::LOAD_IC:
case FeedbackVectorSlotKind::KEYED_LOAD_IC:
case FeedbackVectorSlotKind::STORE_IC:
case FeedbackVectorSlotKind::KEYED_STORE_IC:
case FeedbackVectorSlotKind::GENERAL:
case FeedbackVectorSlotKind::INVALID:
return false;
case FeedbackVectorSlotKind::KINDS_NUMBER:
break;
}
UNREACHABLE();
return false;
}
bool TypeFeedbackVector::is_empty() const {
if (length() == 0) return true;
......@@ -140,15 +158,15 @@ Symbol* TypeFeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
}
bool TypeFeedbackMetadataIterator::HasNext() const {
return slot_.ToInt() < metadata()->slot_count();
return next_slot_.ToInt() < metadata()->slot_count();
}
FeedbackVectorSlot TypeFeedbackMetadataIterator::Next() {
DCHECK(HasNext());
FeedbackVectorSlot slot = slot_;
slot_kind_ = metadata()->GetKind(slot);
slot_ = FeedbackVectorSlot(slot_.ToInt() + entry_size());
return slot;
cur_slot_ = next_slot_;
slot_kind_ = metadata()->GetKind(cur_slot_);
next_slot_ = FeedbackVectorSlot(next_slot_.ToInt() + entry_size());
return cur_slot_;
}
int TypeFeedbackMetadataIterator::entry_size() const {
......
......@@ -37,6 +37,23 @@ FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind(
return VectorICComputer::decode(data, slot.ToInt());
}
String* TypeFeedbackMetadata::GetName(FeedbackVectorSlot slot) const {
DCHECK(SlotRequiresName(GetKind(slot)));
FixedArray* names = FixedArray::cast(get(kNamesTableIndex));
// TODO(ishell): consider using binary search here or even Dictionary when we
// have more ICs with names.
Smi* key = Smi::FromInt(slot.ToInt());
for (int entry = 0; entry < names->length(); entry += kNameTableEntrySize) {
Object* current_key = names->get(entry + kNameTableSlotIndex);
if (current_key == key) {
Object* name = names->get(entry + kNameTableNameIndex);
DCHECK(name->IsString());
return String::cast(name);
}
}
UNREACHABLE();
return nullptr;
}
void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot,
FeedbackVectorSlotKind kind) {
......@@ -57,12 +74,13 @@ template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
template <typename Spec>
Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
const Spec* spec) {
Factory* factory = isolate->factory();
const int slot_count = spec->slots();
const int slot_kinds_length = VectorICComputer::word_count(slot_count);
const int length = slot_kinds_length + kReservedIndexCount;
if (length == kReservedIndexCount) {
return Handle<TypeFeedbackMetadata>::cast(
isolate->factory()->empty_fixed_array());
return Handle<TypeFeedbackMetadata>::cast(factory->empty_fixed_array());
}
#ifdef DEBUG
for (int i = 0; i < slot_count;) {
......@@ -76,7 +94,7 @@ Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
}
#endif
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED);
Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
// Fill the bit-vector part with zeros.
for (int i = 0; i < slot_kinds_length; i++) {
......@@ -85,9 +103,29 @@ Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
Handle<TypeFeedbackMetadata> metadata =
Handle<TypeFeedbackMetadata>::cast(array);
// Add names to NamesTable.
const int name_count = spec->name_count();
Handle<FixedArray> names =
name_count == 0
? factory->empty_fixed_array()
: factory->NewFixedArray(name_count * kNameTableEntrySize);
int name_index = 0;
for (int i = 0; i < slot_count; i++) {
metadata->SetKind(FeedbackVectorSlot(i), spec->GetKind(i));
FeedbackVectorSlotKind kind = spec->GetKind(i);
metadata->SetKind(FeedbackVectorSlot(i), kind);
if (SlotRequiresName(kind)) {
Handle<String> name = spec->GetName(name_index);
DCHECK(!name.is_null());
int entry = name_index * kNameTableEntrySize;
names->set(entry + kNameTableSlotIndex, Smi::FromInt(i));
names->set(entry + kNameTableNameIndex, *name);
name_index++;
}
}
DCHECK_EQ(name_count, name_index);
metadata->set(kNamesTableIndex, *names);
// It's important that the TypeFeedbackMetadata have a COW map, since it's
// pointed to by both a SharedFunctionInfo and indirectly by closures through
......@@ -107,10 +145,24 @@ bool TypeFeedbackMetadata::SpecDiffersFrom(
}
int slots = slot_count();
for (int i = 0; i < slots; i++) {
if (GetKind(FeedbackVectorSlot(i)) != other_spec->GetKind(i)) {
int name_index = 0;
for (int i = 0; i < slots;) {
FeedbackVectorSlot slot(i);
FeedbackVectorSlotKind kind = GetKind(slot);
int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
if (kind != other_spec->GetKind(i)) {
return true;
}
if (SlotRequiresName(kind)) {
String* name = GetName(slot);
DCHECK(name != GetHeap()->empty_string());
String* other_name = *other_spec->GetName(name_index++);
if (name != other_name) {
return true;
}
}
i += entry_size;
}
return false;
}
......@@ -122,11 +174,19 @@ bool TypeFeedbackMetadata::DiffersFrom(
}
int slots = slot_count();
for (int i = 0; i < slots; i++) {
for (int i = 0; i < slots;) {
FeedbackVectorSlot slot(i);
FeedbackVectorSlotKind kind = GetKind(slot);
int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
if (GetKind(slot) != other_metadata->GetKind(slot)) {
return true;
}
if (SlotRequiresName(kind)) {
if (GetName(slot) != other_metadata->GetName(slot)) {
return true;
}
}
i += entry_size;
}
return false;
}
......@@ -162,6 +222,11 @@ FeedbackVectorSlotKind TypeFeedbackVector::GetKind(
return metadata()->GetKind(slot);
}
String* TypeFeedbackVector::GetName(FeedbackVectorSlot slot) const {
DCHECK(!is_empty());
return metadata()->GetName(slot);
}
// static
Handle<TypeFeedbackVector> TypeFeedbackVector::New(
Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) {
......@@ -176,6 +241,8 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::New(
Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
array->set(kMetadataIndex, *metadata);
DisallowHeapAllocation no_gc;
// Ensure we can skip the write barrier
Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel);
......
......@@ -50,7 +50,8 @@ class FeedbackVectorSpecBase {
return AddSlot(FeedbackVectorSlotKind::LOAD_IC);
}
FeedbackVectorSlot AddLoadGlobalICSlot() {
FeedbackVectorSlot AddLoadGlobalICSlot(Handle<String> name) {
This()->append_name(name);
return AddSlot(FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
}
......@@ -69,40 +70,65 @@ class FeedbackVectorSpecBase {
FeedbackVectorSlot AddGeneralSlot() {
return AddSlot(FeedbackVectorSlotKind::GENERAL);
}
#ifdef OBJECT_PRINT
// For gdb debugging.
void Print();
#endif // OBJECT_PRINT
DECLARE_PRINTER(FeedbackVectorSpec)
private:
Derived* This() { return static_cast<Derived*>(this); }
};
class StaticFeedbackVectorSpec
: public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
public:
StaticFeedbackVectorSpec() : slots_(0) {}
StaticFeedbackVectorSpec() : slot_count_(0), name_count_(0) {}
int slots() const { return slots_; }
int slots() const { return slot_count_; }
FeedbackVectorSlotKind GetKind(int slot) const {
DCHECK(slot >= 0 && slot < slots_);
DCHECK(slot >= 0 && slot < slot_count_);
return kinds_[slot];
}
int name_count() const { return name_count_; }
Handle<String> GetName(int index) const {
DCHECK(index >= 0 && index < name_count_);
return names_[index];
}
private:
friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>;
void append(FeedbackVectorSlotKind kind) {
DCHECK(slots_ < kMaxLength);
kinds_[slots_++] = kind;
DCHECK(slot_count_ < kMaxLength);
kinds_[slot_count_++] = kind;
}
void append_name(Handle<String> name) {
DCHECK(name_count_ < kMaxLength);
names_[name_count_++] = name;
}
static const int kMaxLength = 12;
int slots_;
int slot_count_;
FeedbackVectorSlotKind kinds_[kMaxLength];
int name_count_;
Handle<String> names_[kMaxLength];
};
class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
public:
explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) {
explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone), names_(zone) {
slot_kinds_.reserve(16);
names_.reserve(8);
}
int slots() const { return static_cast<int>(slot_kinds_.size()); }
......@@ -111,6 +137,10 @@ class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
return static_cast<FeedbackVectorSlotKind>(slot_kinds_.at(slot));
}
int name_count() const { return static_cast<int>(names_.size()); }
Handle<String> GetName(int index) const { return names_.at(index); }
private:
friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
......@@ -118,13 +148,17 @@ class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
slot_kinds_.push_back(static_cast<unsigned char>(kind));
}
void append_name(Handle<String> name) { names_.push_back(name); }
ZoneVector<unsigned char> slot_kinds_;
ZoneVector<Handle<String>> names_;
};
// The shape of the TypeFeedbackMetadata is an array with:
// 0: slot_count
// 1..N: slot kinds packed into a bit vector
// 1: names table
// 2..N: slot kinds packed into a bit vector
//
class TypeFeedbackMetadata : public FixedArray {
public:
......@@ -132,11 +166,19 @@ class TypeFeedbackMetadata : public FixedArray {
static inline TypeFeedbackMetadata* cast(Object* obj);
static const int kSlotsCountIndex = 0;
static const int kReservedIndexCount = 1;
static const int kNamesTableIndex = 1;
static const int kReservedIndexCount = 2;
static const int kNameTableEntrySize = 2;
static const int kNameTableSlotIndex = 0;
static const int kNameTableNameIndex = 1;
// Returns number of feedback vector elements used by given slot kind.
static inline int GetSlotSize(FeedbackVectorSlotKind kind);
// Defines if slots of given kind require "name".
static inline bool SlotRequiresName(FeedbackVectorSlotKind kind);
bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;
bool DiffersFrom(const TypeFeedbackMetadata* other_metadata) const;
......@@ -149,6 +191,9 @@ class TypeFeedbackMetadata : public FixedArray {
// Returns slot kind for given slot.
FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
// Returns name for given slot.
String* GetName(FeedbackVectorSlot slot) const;
template <typename Spec>
static Handle<TypeFeedbackMetadata> New(Isolate* isolate, const Spec* spec);
......@@ -179,9 +224,9 @@ class TypeFeedbackMetadata : public FixedArray {
// 0: feedback metadata
// 1: ics_with_types
// 2: ics_with_generic_info
// 3: feedback slot #0 (N >= 3)
// 3: feedback slot #0
// ...
// N + slot_count - 1: feedback slot #(slot_count-1)
// 3 + slot_count - 1: feedback slot #(slot_count-1)
//
class TypeFeedbackVector : public FixedArray {
public:
......@@ -215,6 +260,8 @@ class TypeFeedbackVector : public FixedArray {
// Returns slot kind for given slot.
FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
// Returns name corresponding to given slot or an empty string.
String* GetName(FeedbackVectorSlot slot) const;
static Handle<TypeFeedbackVector> New(Isolate* isolate,
Handle<TypeFeedbackMetadata> metadata);
......@@ -289,12 +336,12 @@ class TypeFeedbackMetadataIterator {
public:
explicit TypeFeedbackMetadataIterator(Handle<TypeFeedbackMetadata> metadata)
: metadata_handle_(metadata),
slot_(FeedbackVectorSlot(0)),
next_slot_(FeedbackVectorSlot(0)),
slot_kind_(FeedbackVectorSlotKind::INVALID) {}
explicit TypeFeedbackMetadataIterator(TypeFeedbackMetadata* metadata)
: metadata_(metadata),
slot_(FeedbackVectorSlot(0)),
next_slot_(FeedbackVectorSlot(0)),
slot_kind_(FeedbackVectorSlotKind::INVALID) {}
inline bool HasNext() const;
......@@ -311,6 +358,11 @@ class TypeFeedbackMetadataIterator {
// Returns entry size of the last slot returned by Next().
inline int entry_size() const;
String* name() const {
DCHECK(TypeFeedbackMetadata::SlotRequiresName(kind()));
return metadata()->GetName(cur_slot_);
}
private:
TypeFeedbackMetadata* metadata() const {
return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_;
......@@ -321,7 +373,8 @@ class TypeFeedbackMetadataIterator {
// pointer use cases.
Handle<TypeFeedbackMetadata> metadata_handle_;
TypeFeedbackMetadata* metadata_;
FeedbackVectorSlot slot_;
FeedbackVectorSlot cur_slot_;
FeedbackVectorSlot next_slot_;
FeedbackVectorSlotKind slot_kind_;
};
......
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