[lite] Allocate feedback vectors lazily

Allocate feedback vectors lazily when the function's interrupt budget has
reached a specified threshold. This cl introduces a new field in the
ClosureFeedbackCellArray to track the interrupt budget for allocating
feedback vectors. Using the interrupt budget on the bytecode array could
cause problems when there are closures across native contexts and we may
delay allocating feedback vectors in one of them causing unexpected
performance cliffs. In the long term we may want to remove interrupt budget
from bytecode array and use context specific budget for tiering up decisions
as well.

Bug: v8:8394
Change-Id: Ia8fbb71f5e8543a92f14c44aa762973da82d445c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1520719
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60450}
This commit is contained in:
Mythri 2019-03-25 15:05:47 +00:00 committed by Commit Bot
parent 26ffe82e70
commit 7629afdb9d
48 changed files with 714 additions and 439 deletions

View File

@ -1086,10 +1086,15 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
FrameScope frame_scope(masm, StackFrame::MANUAL);
__ PushStandardFrame(closure);
// Reset code age.
__ mov(r9, Operand(BytecodeArray::kNoAgeBytecodeAge));
__ strb(r9, FieldMemOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kBytecodeAgeOffset));
// Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset are
// 8-bit fields next to each other, so we could just optimize by writing a
// 16-bit. These static asserts guard our assumption is valid.
STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset ==
BytecodeArray::kOSRNestingLevelOffset + kCharSize);
STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0);
__ mov(r9, Operand(0));
__ strh(r9, FieldMemOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kOSRNestingLevelOffset));
// Load the initial bytecode offset.
__ mov(kInterpreterBytecodeOffsetRegister,

View File

@ -1215,9 +1215,14 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Add(fp, sp, StandardFrameConstants::kFixedFrameSizeFromFp);
// Reset code age.
__ Mov(x10, Operand(BytecodeArray::kNoAgeBytecodeAge));
__ Strb(x10, FieldMemOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kBytecodeAgeOffset));
// Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset are
// 8-bit fields next to each other, so we could just optimize by writing a
// 16-bit. These static asserts guard our assumption is valid.
STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset ==
BytecodeArray::kOSRNestingLevelOffset + kCharSize);
STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0);
__ Strh(wzr, FieldMemOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kOSRNestingLevelOffset));
// Load the initial bytecode offset.
__ Mov(kInterpreterBytecodeOffsetRegister,

View File

@ -134,7 +134,8 @@ void LazyBuiltinsAssembler::CompileLazy(TNode<JSFunction> function) {
Label use_sfi_code(this);
// If there is no feedback, don't check for optimized code.
GotoIf(IsFixedArray(feedback_cell_value), &use_sfi_code);
GotoIf(HasInstanceType(feedback_cell_value, CLOSURE_FEEDBACK_CELL_ARRAY_TYPE),
&use_sfi_code);
// If it isn't undefined or fixed array it must be a feedback vector.
CSA_ASSERT(this, IsFeedbackVector(feedback_cell_value));

View File

@ -1014,10 +1014,15 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
AbortReason::kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
}
// Reset code age.
__ mov_b(FieldOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kBytecodeAgeOffset),
Immediate(BytecodeArray::kNoAgeBytecodeAge));
// Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset are
// 8-bit fields next to each other, so we could just optimize by writing a
// 16-bit. These static asserts guard our assumption is valid.
STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset ==
BytecodeArray::kOSRNestingLevelOffset + kCharSize);
STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0);
__ mov_w(FieldOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kOSRNestingLevelOffset),
Immediate(0));
// Push bytecode array.
__ push(kInterpreterBytecodeArrayRegister);

View File

@ -1101,10 +1101,15 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Push(rsi); // Callee's context.
__ Push(rdi); // Callee's JS function.
// Reset code age.
__ movb(FieldOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kBytecodeAgeOffset),
Immediate(BytecodeArray::kNoAgeBytecodeAge));
// Reset code age and the OSR arming. The OSR field and BytecodeAgeOffset are
// 8-bit fields next to each other, so we could just optimize by writing a
// 16-bit. These static asserts guard our assumption is valid.
STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset ==
BytecodeArray::kOSRNestingLevelOffset + kCharSize);
STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0);
__ movw(FieldOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kOSRNestingLevelOffset),
Immediate(0));
// Load initial bytecode offset.
__ movq(kInterpreterBytecodeOffsetRegister,

View File

@ -10045,14 +10045,16 @@ TNode<HeapObject> CodeStubAssembler::LoadFeedbackVector(
return maybe_vector.value();
}
TNode<FixedArray> CodeStubAssembler::LoadClosureFeedbackArray(
TNode<ClosureFeedbackCellArray> CodeStubAssembler::LoadClosureFeedbackArray(
SloppyTNode<JSFunction> closure) {
TVARIABLE(HeapObject, feedback_cell_array, LoadFeedbackCellValue(closure));
Label end(this);
// When feedback vectors are not yet allocated feedback cell contains a
// an array of feedback cells used by create closures.
GotoIf(IsFixedArray(feedback_cell_array.value()), &end);
GotoIf(HasInstanceType(feedback_cell_array.value(),
CLOSURE_FEEDBACK_CELL_ARRAY_TYPE),
&end);
// Load FeedbackCellArray from feedback vector.
TNode<FeedbackVector> vector = CAST(feedback_cell_array.value());

View File

@ -2872,7 +2872,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// used when creating closures from this function. This array could be
// directly hanging off the FeedbackCell when there is no feedback vector
// or available from the feedback vector's header.
TNode<FixedArray> LoadClosureFeedbackArray(SloppyTNode<JSFunction> closure);
TNode<ClosureFeedbackCellArray> LoadClosureFeedbackArray(
SloppyTNode<JSFunction> closure);
// Update the type feedback vector.
void UpdateFeedback(Node* feedback, Node* feedback_vector, Node* slot_id);

View File

@ -297,6 +297,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
case DESCRIPTOR_ARRAY_TYPE:
case TRANSITION_ARRAY_TYPE:
case FEEDBACK_CELL_TYPE:
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
case FEEDBACK_VECTOR_TYPE:
case PROPERTY_ARRAY_TYPE:
case FOREIGN_TYPE:

View File

@ -23,11 +23,14 @@ namespace internal {
OBJECT_CONSTRUCTORS_IMPL(FeedbackVector, HeapObject)
OBJECT_CONSTRUCTORS_IMPL(FeedbackMetadata, HeapObject)
OBJECT_CONSTRUCTORS_IMPL(ClosureFeedbackCellArray, FixedArray)
NEVER_READ_ONLY_SPACE_IMPL(FeedbackVector)
NEVER_READ_ONLY_SPACE_IMPL(ClosureFeedbackCellArray)
CAST_ACCESSOR(FeedbackVector)
CAST_ACCESSOR(FeedbackMetadata)
CAST_ACCESSOR(ClosureFeedbackCellArray)
INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
@ -93,10 +96,17 @@ int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
return 1;
}
SMI_ACCESSORS(ClosureFeedbackCellArray, interrupt_budget,
FixedArray::OffsetOfElementAt(kInterruptBudgetIndex))
Handle<FeedbackCell> ClosureFeedbackCellArray::GetFeedbackCell(int index) {
return handle(FeedbackCell::cast(get(index + kFeedbackCellStartIndex)),
GetIsolate());
}
ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
kSharedFunctionInfoOffset)
WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
ACCESSORS(FeedbackVector, closure_feedback_cell_array, FixedArray,
ACCESSORS(FeedbackVector, closure_feedback_cell_array, ClosureFeedbackCellArray,
kClosureFeedbackCellArrayOffset)
INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
@ -161,8 +171,9 @@ MaybeObject FeedbackVector::get(int index) const {
Handle<FeedbackCell> FeedbackVector::GetClosureFeedbackCell(int index) const {
DCHECK_GE(index, 0);
FixedArray cell_array = closure_feedback_cell_array();
return handle(FeedbackCell::cast(cell_array.get(index)), GetIsolate());
ClosureFeedbackCellArray cell_array =
ClosureFeedbackCellArray::cast(closure_feedback_cell_array());
return cell_array->GetFeedbackCell(index);
}
void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,

View File

@ -206,16 +206,35 @@ FeedbackSlot FeedbackVector::GetTypeProfileSlot() const {
return slot;
}
// static
Handle<ClosureFeedbackCellArray> ClosureFeedbackCellArray::New(
Isolate* isolate, Handle<SharedFunctionInfo> shared) {
Factory* factory = isolate->factory();
int num_feedback_cells =
shared->feedback_metadata()->closure_feedback_cell_count();
Handle<ClosureFeedbackCellArray> feedback_cell_array =
factory->NewClosureFeedbackCellArray(num_feedback_cells);
for (int i = 0; i < num_feedback_cells; i++) {
Handle<FeedbackCell> cell =
factory->NewNoClosuresCell(factory->undefined_value());
feedback_cell_array->set(i + kFeedbackCellStartIndex, *cell);
}
return feedback_cell_array;
}
// static
Handle<FeedbackVector> FeedbackVector::New(
Isolate* isolate, Handle<SharedFunctionInfo> shared,
Handle<FixedArray> closure_feedback_cell_array) {
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array) {
Factory* factory = isolate->factory();
const int slot_count = shared->feedback_metadata()->slot_count();
Handle<FeedbackVector> vector =
factory->NewFeedbackVector(shared, AllocationType::kOld);
Handle<FeedbackVector> vector = factory->NewFeedbackVector(
shared, closure_feedback_cell_array, AllocationType::kOld);
DCHECK_EQ(vector->length(), slot_count);
@ -229,8 +248,6 @@ Handle<FeedbackVector> FeedbackVector::New(
DCHECK_EQ(vector->profiler_ticks(), 0);
DCHECK_EQ(vector->deopt_count(), 0);
vector->set_closure_feedback_cell_array(*closure_feedback_cell_array);
// Ensure we can skip the write barrier
Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
DCHECK_EQ(ReadOnlyRoots(isolate).uninitialized_symbol(),
@ -297,27 +314,6 @@ Handle<FeedbackVector> FeedbackVector::New(
return result;
}
// static
Handle<FixedArray> FeedbackVector::NewClosureFeedbackCellArray(
Isolate* isolate, Handle<SharedFunctionInfo> shared) {
Factory* factory = isolate->factory();
int num_feedback_cells =
shared->feedback_metadata()->closure_feedback_cell_count();
if (num_feedback_cells == 0) {
return factory->empty_fixed_array();
}
Handle<FixedArray> feedback_cell_array =
factory->NewFixedArray(num_feedback_cells, AllocationType::kOld);
for (int i = 0; i < num_feedback_cells; i++) {
Handle<FeedbackCell> cell =
factory->NewNoClosuresCell(factory->undefined_value());
feedback_cell_array->set(i, *cell);
}
return feedback_cell_array;
}
// static
void FeedbackVector::AddToVectorsForProfilingTools(
Isolate* isolate, Handle<FeedbackVector> vector) {

View File

@ -144,6 +144,33 @@ typedef std::vector<MaybeObjectHandle> MaybeObjectHandles;
class FeedbackMetadata;
// ClosureFeedbackCellArray is a FixedArray that contains feedback cells used
// when creating closures from a function. Along with the feedback
// cells, the first slot (slot 0) is used to hold a budget to measure the
// hotness of the function. This is created once the function is compiled and is
// either held by the feedback vector (if allocated) or by the FeedbackCell of
// the closure.
class ClosureFeedbackCellArray : public FixedArray {
public:
NEVER_READ_ONLY_SPACE
DECL_CAST(ClosureFeedbackCellArray)
V8_EXPORT_PRIVATE static Handle<ClosureFeedbackCellArray> New(
Isolate* isolate, Handle<SharedFunctionInfo> shared);
inline Handle<FeedbackCell> GetFeedbackCell(int index);
DECL_INT_ACCESSORS(interrupt_budget)
DECL_VERIFIER(ClosureFeedbackCellArray)
DECL_PRINTER(ClosureFeedbackCellArray)
enum { kInterruptBudgetIndex, kFeedbackCellStartIndex };
private:
OBJECT_CONSTRUCTORS(ClosureFeedbackCellArray, FixedArray);
};
// A FeedbackVector has a fixed header with:
// - shared function info (which includes feedback metadata)
// - invocation count
@ -171,7 +198,7 @@ class FeedbackVector : public HeapObject {
// [feedback_cell_array]: The FixedArray to hold the feedback cells for any
// closures created by this function.
DECL_ACCESSORS(closure_feedback_cell_array, FixedArray)
DECL_ACCESSORS(closure_feedback_cell_array, ClosureFeedbackCellArray)
// [length]: The length of the feedback vector (not including the header, i.e.
// the number of feedback slots).
@ -234,10 +261,7 @@ class FeedbackVector : public HeapObject {
V8_EXPORT_PRIVATE static Handle<FeedbackVector> New(
Isolate* isolate, Handle<SharedFunctionInfo> shared,
Handle<FixedArray> closure_feedback_cell_array);
V8_EXPORT_PRIVATE static Handle<FixedArray> NewClosureFeedbackCellArray(
Isolate* isolate, Handle<SharedFunctionInfo> shared);
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array);
#define DEFINE_SLOT_KIND_PREDICATE(Name) \
bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); }

View File

@ -370,6 +370,11 @@ DEFINE_INT(interrupt_budget, 144 * KB,
#undef FLAG
#define FLAG FLAG_FULL
DEFINE_INT(budget_for_feedback_vector_allocation, 2 * KB,
"The budget in amount of bytecode executed by a function before we "
"decide to allocate feedback vectors")
DEFINE_BOOL(lazy_feedback_allocation, false, "Allocate feedback vectors lazily")
// Flags for Ignition.
DEFINE_BOOL(ignition_elide_noneffectful_bytecodes, true,
"elide bytecodes which won't have any external effect")
@ -1230,7 +1235,7 @@ DEFINE_NEG_IMPLICATION(jitless, wasm_lazy_compilation)
DEFINE_BOOL(opt, !V8_LITE_BOOL, "use adaptive optimizations")
// Enable use of inline caches to optimize object access operations.
DEFINE_BOOL(use_ic, !V8_LITE_BOOL, "use inline caching")
DEFINE_BOOL(use_ic, true, "use inline caching")
// Favor memory over execution speed.
DEFINE_BOOL(optimize_for_size, V8_LITE_BOOL,
@ -1543,6 +1548,7 @@ DEFINE_BOOL(raw_heap_snapshots, V8_ENABLE_RAW_HEAP_SNAPSHOTS_BOOL,
DEFINE_BOOL(lite_mode, V8_LITE_BOOL,
"enables trade-off of performance for memory savings "
"(Lite mode only)")
DEFINE_IMPLICATION(lite_mode, lazy_feedback_allocation)
// Cleanup...
#undef FLAG_FULL

View File

@ -418,8 +418,25 @@ Handle<FixedArray> Factory::NewUninitializedFixedArray(
*undefined_value(), allocation);
}
Handle<ClosureFeedbackCellArray> Factory::NewClosureFeedbackCellArray(
int num_slots, AllocationType allocation) {
int length = ClosureFeedbackCellArray::kFeedbackCellStartIndex + num_slots;
Handle<ClosureFeedbackCellArray> feedback_cell_array =
NewFixedArrayWithMap<ClosureFeedbackCellArray>(
RootIndex::kClosureFeedbackCellArrayMap, length, allocation);
// Initialize header fields
feedback_cell_array->set_interrupt_budget(
FLAG_budget_for_feedback_vector_allocation);
DCHECK_EQ(ClosureFeedbackCellArray::kFeedbackCellStartIndex, 1);
return feedback_cell_array;
}
Handle<FeedbackVector> Factory::NewFeedbackVector(
Handle<SharedFunctionInfo> shared, AllocationType allocation) {
Handle<SharedFunctionInfo> shared,
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array,
AllocationType allocation) {
int length = shared->feedback_metadata()->slot_count();
DCHECK_LE(0, length);
int size = FeedbackVector::SizeFor(length);
@ -435,7 +452,7 @@ Handle<FeedbackVector> Factory::NewFeedbackVector(
vector->set_invocation_count(0);
vector->set_profiler_ticks(0);
vector->set_deopt_count(0);
vector->set_closure_feedback_cell_array(*empty_fixed_array());
vector->set_closure_feedback_cell_array(*closure_feedback_cell_array);
// TODO(leszeks): Initialize based on the feedback metadata.
MemsetTagged(ObjectSlot(vector->slots_start()), *undefined_value(), length);

View File

@ -156,10 +156,16 @@ class V8_EXPORT_PRIVATE Factory {
Handle<FixedArray> NewUninitializedFixedArray(
int length, AllocationType allocation = AllocationType::kYoung);
// Allocates a closure feedback cell array whose feedback cells are
// initialized with undefined values.
Handle<ClosureFeedbackCellArray> NewClosureFeedbackCellArray(
int num_slots, AllocationType allocation = AllocationType::kYoung);
// Allocates a feedback vector whose slots are initialized with undefined
// values.
Handle<FeedbackVector> NewFeedbackVector(
Handle<SharedFunctionInfo> shared,
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array,
AllocationType allocation = AllocationType::kYoung);
// Allocates a clean embedder data array with given capacity.

View File

@ -616,13 +616,6 @@ void ObjectStatsCollectorImpl::RecordVirtualFeedbackVectorDetails(
size_t calculated_size = 0;
// Log the feedback_cell array used for create closures.
RecordVirtualObjectStats(
vector, vector->closure_feedback_cell_array(),
ObjectStats::FEEDBACK_VECTOR_CREATE_CLOSURE_ARRAY_TYPE,
vector->closure_feedback_cell_array()->Size(),
ObjectStats::kNoOverAllocation);
// Log the feedback vector's header (fixed fields).
size_t header_size = vector->slots_start().address() - vector->address();
stats_->RecordVirtualObjectStats(ObjectStats::FEEDBACK_VECTOR_HEADER_TYPE,

View File

@ -31,7 +31,6 @@
V(ENUM_INDICES_CACHE_TYPE) \
V(FEEDBACK_VECTOR_ENTRY_TYPE) \
V(FEEDBACK_VECTOR_HEADER_TYPE) \
V(FEEDBACK_VECTOR_CREATE_CLOSURE_ARRAY_TYPE) \
V(FEEDBACK_VECTOR_SLOT_CALL_TYPE) \
V(FEEDBACK_VECTOR_SLOT_CALL_UNUSED_TYPE) \
V(FEEDBACK_VECTOR_SLOT_ENUM_TYPE) \

View File

@ -369,6 +369,8 @@ bool Heap::CreateInitialMaps() {
ALLOCATE_VARSIZE_MAP(SCOPE_INFO_TYPE, scope_info)
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, module_info)
ALLOCATE_VARSIZE_MAP(CLOSURE_FEEDBACK_CELL_ARRAY_TYPE,
closure_feedback_cell_array)
ALLOCATE_VARSIZE_MAP(FEEDBACK_VECTOR_TYPE, feedback_vector)
ALLOCATE_PRIMITIVE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number,
Context::NUMBER_FUNCTION_INDEX)

View File

@ -1253,48 +1253,73 @@ Node* InterpreterAssembler::CallRuntimeN(Node* function_id, Node* context,
void InterpreterAssembler::UpdateInterruptBudget(Node* weight, bool backward) {
Comment("[ UpdateInterruptBudget");
Node* budget_offset =
IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag);
// Assert that the weight is positive (negative weights should be implemented
// as backward updates).
CSA_ASSERT(this, Int32GreaterThanOrEqual(weight, Int32Constant(0)));
// Update budget by |weight| and check if it reaches zero.
Variable new_budget(this, MachineRepresentation::kWord32);
Node* old_budget =
Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset);
Label load_budget_from_bytecode(this), load_budget_done(this);
TNode<JSFunction> function = CAST(LoadRegister(Register::function_closure()));
TNode<HeapObject> feedback_cell_value = LoadFeedbackCellValue(function);
Node* budget_offset =
IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag);
TVARIABLE(Int32T, old_budget);
// TODO(mythria): We should use the interrupt budget on the feedback vector
// for updating runtime profiler ticks as well. That would avoid having two
// different places where we track interrupt budget.
GotoIf(IsFeedbackVector(feedback_cell_value), &load_budget_from_bytecode);
TNode<FixedArray> closure_feedback_cell_array = CAST(feedback_cell_value);
TNode<Smi> old_budget_smi = CAST(
LoadFixedArrayElement(closure_feedback_cell_array,
ClosureFeedbackCellArray::kInterruptBudgetIndex));
old_budget = SmiToInt32(old_budget_smi);
Goto(&load_budget_done);
BIND(&load_budget_from_bytecode);
old_budget = UncheckedCast<Int32T>(
Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset));
Goto(&load_budget_done);
BIND(&load_budget_done);
// Make sure we include the current bytecode in the budget calculation.
Node* budget_after_bytecode =
Int32Sub(old_budget, Int32Constant(CurrentBytecodeSize()));
TNode<Int32T> budget_after_bytecode = Signed(
Int32Sub(old_budget.value(), Int32Constant(CurrentBytecodeSize())));
TVARIABLE(Int32T, new_budget);
if (backward) {
new_budget.Bind(Int32Sub(budget_after_bytecode, weight));
// Update budget by |weight| and check if it reaches zero.
new_budget = Signed(Int32Sub(budget_after_bytecode, weight));
Node* condition =
Int32GreaterThanOrEqual(new_budget.value(), Int32Constant(0));
Label ok(this), interrupt_check(this, Label::kDeferred);
Label ok(this), interrupt_check(this);
Branch(condition, &ok, &interrupt_check);
// Perform interrupt and reset budget.
BIND(&interrupt_check);
{
CallRuntime(Runtime::kInterrupt, GetContext());
new_budget.Bind(Int32Constant(Interpreter::InterruptBudget()));
Goto(&ok);
}
CallRuntime(Runtime::kBytecodeBudgetInterrupt, GetContext(), function);
new_budget = Int32Constant(Interpreter::InterruptBudget());
Goto(&ok);
BIND(&ok);
} else {
// For a forward jump, we know we only increase the interrupt budget, so
// no need to check if it's below zero.
new_budget.Bind(Int32Add(budget_after_bytecode, weight));
new_budget = Signed(Int32Add(budget_after_bytecode, weight));
}
// Update budget.
Label update_budget_in_bytecode(this), end(this);
GotoIf(IsFeedbackVector(feedback_cell_value), &update_budget_in_bytecode);
StoreFixedArrayElement(closure_feedback_cell_array,
ClosureFeedbackCellArray::kInterruptBudgetIndex,
SmiFromInt32(new_budget.value()), SKIP_WRITE_BARRIER);
Goto(&end);
BIND(&update_budget_in_bytecode);
StoreNoWriteBarrier(MachineRepresentation::kWord32,
BytecodeArrayTaggedPointer(), budget_offset,
new_budget.value());
Goto(&end);
BIND(&end);
Comment("] UpdateInterruptBudget");
}

View File

@ -2634,8 +2634,9 @@ IGNITION_HANDLER(CreateClosure, InterpreterAssembler) {
Label if_undefined(this);
TNode<FixedArray> feedback_cell_array =
LoadClosureFeedbackArray(LoadRegister(Register::function_closure()));
TNode<FeedbackCell> feedback_cell =
CAST(LoadFixedArrayElement(feedback_cell_array, slot));
TNode<FeedbackCell> feedback_cell = CAST(LoadFixedArrayElement(
feedback_cell_array, slot,
ClosureFeedbackCellArray::kFeedbackCellStartIndex * kTaggedSize));
Label if_fast(this), if_slow(this, Label::kDeferred);
Branch(IsSetWord32<CreateClosureFlags::FastNewClosureBit>(flags), &if_fast,

View File

@ -832,6 +832,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
p4);
case FIXED_ARRAY_TYPE:
case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
case HASH_TABLE_TYPE:
case ORDERED_HASH_MAP_TYPE:
case ORDERED_HASH_SET_TYPE:

View File

@ -168,6 +168,7 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
EmbedderDataArray::cast(*this)->EmbedderDataArrayVerify(isolate);
break;
// FixedArray types
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
case HASH_TABLE_TYPE:
case ORDERED_HASH_MAP_TYPE:
case ORDERED_HASH_SET_TYPE:

View File

@ -129,6 +129,7 @@ namespace internal {
\
V(FIXED_ARRAY_TYPE) \
V(OBJECT_BOILERPLATE_DESCRIPTION_TYPE) \
V(CLOSURE_FEEDBACK_CELL_ARRAY_TYPE) \
V(HASH_TABLE_TYPE) \
V(ORDERED_HASH_MAP_TYPE) \
V(ORDERED_HASH_SET_TYPE) \

View File

@ -197,6 +197,9 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case FEEDBACK_CELL_TYPE:
FeedbackCell::cast(*this)->FeedbackCellPrint(os);
break;
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
ClosureFeedbackCellArray::cast(*this)->ClosureFeedbackCellArrayPrint(os);
break;
case FEEDBACK_VECTOR_TYPE:
FeedbackVector::cast(*this)->FeedbackVectorPrint(os);
break;
@ -1086,6 +1089,10 @@ void FeedbackMetadata::FeedbackMetadataPrint(std::ostream& os) {
os << "\n";
}
void ClosureFeedbackCellArray::ClosureFeedbackCellArrayPrint(std::ostream& os) {
PrintFixedArrayWithHeader(os, *this, "ClosureFeedbackCellArray");
}
void FeedbackVector::FeedbackVectorPrint(std::ostream& os) { // NOLINT
PrintHeader(os, "FeedbackVector");
os << "\n - length: " << length();

View File

@ -1988,6 +1988,10 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
}
break;
}
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
os << "<ClosureFeedbackCellArray["
<< ClosureFeedbackCellArray::cast(*this)->length() << "]>";
break;
case FEEDBACK_VECTOR_TYPE:
os << "<FeedbackVector[" << FeedbackVector::cast(*this)->length() << "]>";
break;

View File

@ -99,6 +99,7 @@
// - ScopeInfo
// - ModuleInfo
// - ScriptContextTable
// - ClosureFeedbackCellArray
// - FixedDoubleArray
// - Name
// - String
@ -256,6 +257,7 @@ class AllocationSite;
class ByteArray;
class CachedTemplateObject;
class Cell;
class ClosureFeedbackCellArray;
class ConsString;
class DependentCode;
class ElementsAccessor;
@ -345,6 +347,7 @@ class ZoneForwardList;
V(Constructor) \
V(Context) \
V(CoverageInfo) \
V(ClosureFeedbackCellArray) \
V(DataHandler) \
V(DeoptimizationData) \
V(DependentCode) \

View File

@ -830,6 +830,11 @@ class BytecodeArray : public FixedArrayBase {
BYTECODE_ARRAY_FIELDS)
#undef BYTECODE_ARRAY_FIELDS
// InterpreterEntryTrampoline expects these fields to be next to each other
// and writes a 16-bit value to reset them.
STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset ==
kOSRNestingLevelOffset + kCharSize);
// Maximal memory consumption for a single BytecodeArray.
static const int kMaxSize = 512 * MB;
// Maximal length of a single BytecodeArray.

View File

@ -195,6 +195,7 @@ enum InstanceType : uint16_t {
// FixedArrays.
FIXED_ARRAY_TYPE, // FIRST_FIXED_ARRAY_TYPE
OBJECT_BOILERPLATE_DESCRIPTION_TYPE,
CLOSURE_FEEDBACK_CELL_ARRAY_TYPE,
HASH_TABLE_TYPE, // FIRST_HASH_TABLE_TYPE
ORDERED_HASH_MAP_TYPE, // FIRST_DICTIONARY_TYPE
ORDERED_HASH_SET_TYPE,
@ -408,6 +409,7 @@ V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
V(CachedTemplateObject, TUPLE3_TYPE) \
V(CodeDataContainer, CODE_DATA_CONTAINER_TYPE) \
V(CoverageInfo, FIXED_ARRAY_TYPE) \
V(ClosureFeedbackCellArray, CLOSURE_FEEDBACK_CELL_ARRAY_TYPE) \
V(DescriptorArray, DESCRIPTOR_ARRAY_TYPE) \
V(EmbedderDataArray, EMBEDDER_DATA_ARRAY_TYPE) \
V(EphemeronHashTable, EPHEMERON_HASH_TABLE_TYPE) \

View File

@ -467,9 +467,9 @@ FeedbackVector JSFunction::feedback_vector() const {
return FeedbackVector::cast(raw_feedback_cell()->value());
}
FixedArray JSFunction::closure_feedback_cell_array() const {
ClosureFeedbackCellArray JSFunction::closure_feedback_cell_array() const {
DCHECK(has_closure_feedback_cell_array());
return FixedArray::cast(raw_feedback_cell()->value());
return ClosureFeedbackCellArray::cast(raw_feedback_cell()->value());
}
// Code objects that are marked for deoptimization are not considered to be
@ -589,14 +589,12 @@ void JSFunction::SetOptimizationMarker(OptimizationMarker marker) {
bool JSFunction::has_feedback_vector() const {
return shared()->is_compiled() &&
!raw_feedback_cell()->value()->IsUndefined() &&
raw_feedback_cell()->value()->IsFeedbackVector();
}
bool JSFunction::has_closure_feedback_cell_array() const {
return shared()->is_compiled() &&
!raw_feedback_cell()->value()->IsUndefined() &&
raw_feedback_cell()->value()->IsFixedArray();
raw_feedback_cell()->value()->IsClosureFeedbackCellArray();
}
Context JSFunction::context() {

View File

@ -4938,7 +4938,7 @@ void JSFunction::EnsureClosureFeedbackCellArray(Handle<JSFunction> function) {
Handle<SharedFunctionInfo> shared(function->shared(), isolate);
DCHECK(function->shared()->HasBytecodeArray());
Handle<HeapObject> feedback_cell_array =
FeedbackVector::NewClosureFeedbackCellArray(isolate, shared);
ClosureFeedbackCellArray::New(isolate, shared);
// Many closure cell is used as a way to specify that there is no
// feedback cell for this function and a new feedback cell has to be
// allocated for this funciton. For ex: for eval functions, we have to create
@ -4966,7 +4966,7 @@ void JSFunction::EnsureFeedbackVector(Handle<JSFunction> function) {
DCHECK(function->shared()->HasBytecodeArray());
EnsureClosureFeedbackCellArray(function);
Handle<FixedArray> closure_feedback_cell_array =
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array =
handle(function->closure_feedback_cell_array(), isolate);
Handle<HeapObject> feedback_vector =
FeedbackVector::New(isolate, shared, closure_feedback_cell_array);
@ -4980,7 +4980,7 @@ void JSFunction::EnsureFeedbackVector(Handle<JSFunction> function) {
// static
void JSFunction::InitializeFeedbackCell(Handle<JSFunction> function) {
if (FLAG_lite_mode) {
if (FLAG_lazy_feedback_allocation) {
EnsureClosureFeedbackCellArray(function);
} else {
EnsureFeedbackVector(function);

View File

@ -1036,7 +1036,7 @@ class JSFunction : public JSObject {
// cell arrays after compile, when we want to allocate feedback vectors
// lazily.
inline bool has_closure_feedback_cell_array() const;
inline FixedArray closure_feedback_cell_array() const;
inline ClosureFeedbackCellArray closure_feedback_cell_array() const;
static void EnsureClosureFeedbackCellArray(Handle<JSFunction> function);
// Initializes the feedback cell of |function|. In lite mode, this would be

View File

@ -133,6 +133,7 @@ VisitorId Map::GetVisitorId(Map map) {
case FIXED_ARRAY_TYPE:
case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
case HASH_TABLE_TYPE:
case ORDERED_HASH_MAP_TYPE:
case ORDERED_HASH_SET_TYPE:

View File

@ -60,6 +60,8 @@ class RootVisitor;
V(Map, foreign_map, ForeignMap) \
V(Map, heap_number_map, HeapNumberMap) \
V(Map, transition_array_map, TransitionArrayMap) \
/* TODO(mythria): Once lazy feedback lands, check if feedback vector map */ \
/* is still a popular map */ \
V(Map, feedback_vector_map, FeedbackVectorMap) \
V(ScopeInfo, empty_scope_info, EmptyScopeInfo) \
V(FixedArray, empty_fixed_array, EmptyFixedArray) \
@ -83,6 +85,7 @@ class RootVisitor;
V(Map, debug_evaluate_context_map, DebugEvaluateContextMap) \
V(Map, script_context_table_map, ScriptContextTableMap) \
/* Maps */ \
V(Map, closure_feedback_cell_array_map, ClosureFeedbackCellArrayMap) \
V(Map, feedback_metadata_map, FeedbackMetadataArrayMap) \
V(Map, array_list_map, ArrayListMap) \
V(Map, bigint_map, BigIntMap) \

View File

@ -13,6 +13,7 @@
#include "src/conversions.h"
#include "src/counters.h"
#include "src/debug/debug.h"
#include "src/feedback-vector-inl.h"
#include "src/frames-inl.h"
#include "src/isolate-inl.h"
#include "src/message-template.h"
@ -271,6 +272,25 @@ RUNTIME_FUNCTION(Runtime_StackGuard) {
return isolate->stack_guard()->HandleInterrupts();
}
RUNTIME_FUNCTION(Runtime_BytecodeBudgetInterrupt) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
if (!function->has_feedback_vector()) {
JSFunction::EnsureFeedbackVector(function);
// Also initialize the invocation count here. This is only really needed for
// OSR. When we OSR functions with lazy feedback allocation we want to have
// a non zero invocation count so we can inline functions.
function->feedback_vector()->set_invocation_count(1);
return ReadOnlyRoots(isolate).undefined_value();
}
// Handle interrupts.
{
SealHandleScope shs(isolate);
return isolate->stack_guard()->HandleInterrupts();
}
}
RUNTIME_FUNCTION(Runtime_Interrupt) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());

View File

@ -140,15 +140,16 @@ Object DeclareGlobals(Isolate* isolate, Handle<FixedArray> declarations,
Handle<Context> context(isolate->context(), isolate);
Handle<FeedbackVector> feedback_vector = Handle<FeedbackVector>::null();
Handle<FixedArray> closure_feedback_cell_array = Handle<FixedArray>::null();
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array =
Handle<ClosureFeedbackCellArray>::null();
if (closure->has_feedback_vector()) {
feedback_vector =
Handle<FeedbackVector>(closure->feedback_vector(), isolate);
closure_feedback_cell_array = Handle<FixedArray>(
closure_feedback_cell_array = Handle<ClosureFeedbackCellArray>(
feedback_vector->closure_feedback_cell_array(), isolate);
} else {
closure_feedback_cell_array =
Handle<FixedArray>(closure->closure_feedback_cell_array(), isolate);
closure_feedback_cell_array = Handle<ClosureFeedbackCellArray>(
closure->closure_feedback_cell_array(), isolate);
}
// Traverse the name/value pairs and set the properties.
@ -167,10 +168,9 @@ Object DeclareGlobals(Isolate* isolate, Handle<FixedArray> declarations,
Handle<Object> value;
if (is_function) {
DCHECK(possibly_feedback_cell_slot->IsSmi());
Handle<FeedbackCell> feedback_cell = Handle<FeedbackCell>(
FeedbackCell::cast(closure_feedback_cell_array->get(
Smi::ToInt(*possibly_feedback_cell_slot))),
isolate);
Handle<FeedbackCell> feedback_cell =
closure_feedback_cell_array->GetFeedbackCell(
Smi::ToInt(*possibly_feedback_cell_slot));
// Copy the function and update its context. Use it as value.
Handle<SharedFunctionInfo> shared =
Handle<SharedFunctionInfo>::cast(initial_value);

View File

@ -299,6 +299,39 @@ RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
return ReadOnlyRoots(isolate).undefined_value();
}
namespace {
bool EnsureFeedbackVector(Handle<JSFunction> function) {
// Check function allows lazy compilation.
if (!function->shared()->allows_lazy_compilation()) {
return false;
}
// If function isn't compiled, compile it now.
IsCompiledScope is_compiled_scope(function->shared()->is_compiled_scope());
if (!is_compiled_scope.is_compiled() &&
!Compiler::Compile(function, Compiler::CLEAR_EXCEPTION,
&is_compiled_scope)) {
return false;
}
// Ensure function has a feedback vector to hold type feedback for
// optimization.
JSFunction::EnsureFeedbackVector(function);
return true;
}
} // namespace
RUNTIME_FUNCTION(Runtime_EnsureFeedbackVectorForFunction) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
EnsureFeedbackVector(function);
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_PrepareFunctionForOptimization) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
@ -307,23 +340,10 @@ RUNTIME_FUNCTION(Runtime_PrepareFunctionForOptimization) {
// Only one function should be prepared for optimization at a time
CHECK(isolate->heap()->pending_optimize_for_test_bytecode()->IsUndefined());
// Check function allows lazy compilation.
if (!function->shared()->allows_lazy_compilation()) {
if (!EnsureFeedbackVector(function)) {
return ReadOnlyRoots(isolate).undefined_value();
}
// If function isn't compiled, compile it now.
IsCompiledScope is_compiled_scope(function->shared()->is_compiled_scope());
if (!is_compiled_scope.is_compiled() &&
!Compiler::Compile(function, Compiler::CLEAR_EXCEPTION,
&is_compiled_scope)) {
return ReadOnlyRoots(isolate).undefined_value();
}
// Ensure function has a feedback vector to hold type feedback for
// optimization.
JSFunction::EnsureFeedbackVector(function);
// If optimization is disabled for the function, return without making it
// pending optimize for test.
if (function->shared()->optimization_disabled() &&

View File

@ -219,6 +219,7 @@ namespace internal {
F(GetTemplateObject, 3, 1) \
F(IncrementUseCounter, 1, 1) \
F(Interrupt, 0, 1) \
F(BytecodeBudgetInterrupt, 1, 1) \
F(NewReferenceError, 2, 1) \
F(NewSyntaxError, 2, 1) \
F(NewTypeError, 2, 1) \
@ -494,6 +495,7 @@ namespace internal {
F(NotifyContextDisposed, 0, 1) \
F(OptimizeFunctionOnNextCall, -1, 1) \
F(OptimizeOsr, -1, 1) \
F(EnsureFeedbackVectorForFunction, 1, 1) \
F(PrepareFunctionForOptimization, 1, 1) \
F(PrintWithNameForAssert, 2, 1) \
F(RedirectToWasmInterpreter, 2, 1) \

View File

@ -555,6 +555,12 @@
'test-cpu-profiler/TickLinesBaseline': [SKIP],
'test-cpu-profiler/TickLinesOptimized': [SKIP],
'test-cpu-profiler/Inlining2': [SKIP],
# TODO(mythria): Code logging tests that currently fail with lazy feedback
# allocation. Fix logging to work without feedback vectors and enable these
# tests in lite_mode.
'test-log/ExternalCodeEventListenerWithInterpretedFramesNativeStack': [SKIP],
'test-log/LogInterpretedFramesNativeStack': [SKIP]
}], # lite_mode
##############################################################################

View File

@ -3224,6 +3224,7 @@ TEST(IncrementalMarkingPreservesMonomorphicCallIC) {
if (!FLAG_use_ic) return;
if (!FLAG_incremental_marking) return;
if (FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Value> fun1, fun2;
@ -3241,7 +3242,9 @@ TEST(IncrementalMarkingPreservesMonomorphicCallIC) {
// Prepare function f that contains type feedback for the two closures.
CHECK(CcTest::global()->Set(ctx, v8_str("fun1"), fun1).FromJust());
CHECK(CcTest::global()->Set(ctx, v8_str("fun2"), fun2).FromJust());
CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);");
CompileRun(
"function f(a, b) { a(); b(); } %EnsureFeedbackVectorForFunction(f); "
"f(fun1, fun2);");
Handle<JSFunction> f = Handle<JSFunction>::cast(
v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
@ -3276,9 +3279,9 @@ static void CheckVectorIC(Handle<JSFunction> f, int slot_index,
}
TEST(IncrementalMarkingPreservesMonomorphicConstructor) {
if (FLAG_lite_mode) return;
if (!FLAG_incremental_marking) return;
if (FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
@ -3286,7 +3289,9 @@ TEST(IncrementalMarkingPreservesMonomorphicConstructor) {
// originating from the same native context.
CompileRun(
"function fun() { this.x = 1; };"
"function f(o) { return new o(); } f(fun); f(fun);");
"function f(o) { return new o(); }"
"%EnsureFeedbackVectorForFunction(f);"
"f(fun); f(fun);");
Handle<JSFunction> f = Handle<JSFunction>::cast(
v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
@ -3304,13 +3309,16 @@ TEST(IncrementalMarkingPreservesMonomorphicIC) {
if (!FLAG_use_ic) return;
if (!FLAG_incremental_marking) return;
if (FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
// Prepare function f that contains a monomorphic IC for object
// originating from the same native context.
CompileRun("function fun() { this.x = 1; }; var obj = new fun();"
"function f(o) { return o.x; } f(obj); f(obj);");
CompileRun(
"function fun() { this.x = 1; }; var obj = new fun();"
"%EnsureFeedbackVectorForFunction(f);"
"function f(o) { return o.x; } f(obj); f(obj);");
Handle<JSFunction> f = Handle<JSFunction>::cast(
v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
@ -3327,6 +3335,7 @@ TEST(IncrementalMarkingPreservesPolymorphicIC) {
if (!FLAG_use_ic) return;
if (!FLAG_incremental_marking) return;
if (FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Value> obj1, obj2;
@ -3348,7 +3357,10 @@ TEST(IncrementalMarkingPreservesPolymorphicIC) {
// originating from two different native contexts.
CHECK(CcTest::global()->Set(ctx, v8_str("obj1"), obj1).FromJust());
CHECK(CcTest::global()->Set(ctx, v8_str("obj2"), obj2).FromJust());
CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);");
CompileRun(
"function f(o) { return o.x; }; "
"%EnsureFeedbackVectorForFunction(f);"
"f(obj1); f(obj1); f(obj2);");
Handle<JSFunction> f = Handle<JSFunction>::cast(
v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
@ -3366,6 +3378,7 @@ TEST(ContextDisposeDoesntClearPolymorphicIC) {
if (!FLAG_use_ic) return;
if (!FLAG_incremental_marking) return;
if (FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Value> obj1, obj2;
@ -3387,7 +3400,10 @@ TEST(ContextDisposeDoesntClearPolymorphicIC) {
// originating from two different native contexts.
CHECK(CcTest::global()->Set(ctx, v8_str("obj1"), obj1).FromJust());
CHECK(CcTest::global()->Set(ctx, v8_str("obj2"), obj2).FromJust());
CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);");
CompileRun(
"function f(o) { return o.x; }; "
"%EnsureFeedbackVectorForFunction(f);"
"f(obj1); f(obj1); f(obj2);");
Handle<JSFunction> f = Handle<JSFunction>::cast(
v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
@ -4481,6 +4497,7 @@ TEST(WeakFunctionInConstructor) {
void CheckWeakness(const char* source) {
FLAG_stress_compaction = false;
FLAG_stress_incremental_marking = false;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
LocalContext env;
@ -4503,17 +4520,19 @@ void CheckWeakness(const char* source) {
// Each of the following "weak IC" tests creates an IC that embeds a map with
// the prototype pointing to _proto_ and checks that the _proto_ dies on GC.
TEST(WeakMapInMonomorphicLoadIC) {
CheckWeakness("function loadIC(obj) {"
" return obj.name;"
"}"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
" loadIC(obj);"
" loadIC(obj);"
" loadIC(obj);"
" return proto;"
" })();");
CheckWeakness(
"function loadIC(obj) {"
" return obj.name;"
"}"
"%EnsureFeedbackVectorForFunction(loadIC);"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
" loadIC(obj);"
" loadIC(obj);"
" loadIC(obj);"
" return proto;"
" })();");
}
@ -4522,6 +4541,7 @@ TEST(WeakMapInPolymorphicLoadIC) {
"function loadIC(obj) {"
" return obj.name;"
"}"
"%EnsureFeedbackVectorForFunction(loadIC);"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
@ -4537,17 +4557,19 @@ TEST(WeakMapInPolymorphicLoadIC) {
TEST(WeakMapInMonomorphicKeyedLoadIC) {
CheckWeakness("function keyedLoadIC(obj, field) {"
" return obj[field];"
"}"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
" keyedLoadIC(obj, 'name');"
" keyedLoadIC(obj, 'name');"
" keyedLoadIC(obj, 'name');"
" return proto;"
" })();");
CheckWeakness(
"function keyedLoadIC(obj, field) {"
" return obj[field];"
"}"
"%EnsureFeedbackVectorForFunction(keyedLoadIC);"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
" keyedLoadIC(obj, 'name');"
" keyedLoadIC(obj, 'name');"
" keyedLoadIC(obj, 'name');"
" return proto;"
" })();");
}
@ -4556,6 +4578,7 @@ TEST(WeakMapInPolymorphicKeyedLoadIC) {
"function keyedLoadIC(obj, field) {"
" return obj[field];"
"}"
"%EnsureFeedbackVectorForFunction(keyedLoadIC);"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
@ -4571,17 +4594,19 @@ TEST(WeakMapInPolymorphicKeyedLoadIC) {
TEST(WeakMapInMonomorphicStoreIC) {
CheckWeakness("function storeIC(obj, value) {"
" obj.name = value;"
"}"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
" storeIC(obj, 'x');"
" storeIC(obj, 'x');"
" storeIC(obj, 'x');"
" return proto;"
" })();");
CheckWeakness(
"function storeIC(obj, value) {"
" obj.name = value;"
"}"
"%EnsureFeedbackVectorForFunction(storeIC);"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
" storeIC(obj, 'x');"
" storeIC(obj, 'x');"
" storeIC(obj, 'x');"
" return proto;"
" })();");
}
@ -4590,6 +4615,7 @@ TEST(WeakMapInPolymorphicStoreIC) {
"function storeIC(obj, value) {"
" obj.name = value;"
"}"
"%EnsureFeedbackVectorForFunction(storeIC);"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
@ -4605,17 +4631,19 @@ TEST(WeakMapInPolymorphicStoreIC) {
TEST(WeakMapInMonomorphicKeyedStoreIC) {
CheckWeakness("function keyedStoreIC(obj, field, value) {"
" obj[field] = value;"
"}"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
" keyedStoreIC(obj, 'x');"
" keyedStoreIC(obj, 'x');"
" keyedStoreIC(obj, 'x');"
" return proto;"
" })();");
CheckWeakness(
"function keyedStoreIC(obj, field, value) {"
" obj[field] = value;"
"}"
"%EnsureFeedbackVectorForFunction(keyedStoreIC);"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
" keyedStoreIC(obj, 'x');"
" keyedStoreIC(obj, 'x');"
" keyedStoreIC(obj, 'x');"
" return proto;"
" })();");
}
@ -4624,6 +4652,7 @@ TEST(WeakMapInPolymorphicKeyedStoreIC) {
"function keyedStoreIC(obj, field, value) {"
" obj[field] = value;"
"}"
"%EnsureFeedbackVectorForFunction(keyedStoreIC);"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
@ -4639,17 +4668,20 @@ TEST(WeakMapInPolymorphicKeyedStoreIC) {
TEST(WeakMapInMonomorphicCompareNilIC) {
CheckWeakness("function compareNilIC(obj) {"
" return obj == null;"
"}"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
" compareNilIC(obj);"
" compareNilIC(obj);"
" compareNilIC(obj);"
" return proto;"
" })();");
FLAG_allow_natives_syntax = true;
CheckWeakness(
"function compareNilIC(obj) {"
" return obj == null;"
"}"
"%EnsureFeedbackVectorForFunction(compareNilIC);"
" (function() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
" compareNilIC(obj);"
" compareNilIC(obj);"
" compareNilIC(obj);"
" return proto;"
" })();");
}
@ -4676,10 +4708,12 @@ TEST(MonomorphicStaysMonomorphicAfterGC) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
v8::HandleScope scope(CcTest::isolate());
FLAG_allow_natives_syntax = true;
CompileRun(
"function loadIC(obj) {"
" return obj.name;"
"}"
"%EnsureFeedbackVectorForFunction(loadIC);"
"function testIC() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"
@ -4710,10 +4744,12 @@ TEST(PolymorphicStaysPolymorphicAfterGC) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
v8::HandleScope scope(CcTest::isolate());
FLAG_allow_natives_syntax = true;
CompileRun(
"function loadIC(obj) {"
" return obj.name;"
"}"
"%EnsureFeedbackVectorForFunction(loadIC);"
"function testIC() {"
" var proto = {'name' : 'weak'};"
" var obj = Object.create(proto);"

View File

@ -29,8 +29,10 @@ Handle<FeedbackVector> CreateFeedbackVectorForTest(
Handle<Object> obj = v8::Utils::OpenHandle(*script);
Handle<SharedFunctionInfo> shared_function =
Handle<SharedFunctionInfo>(JSFunction::cast(*obj)->shared(), i_isolate);
Handle<FeedbackVector> fv =
factory->NewFeedbackVector(shared_function, allocation);
Handle<ClosureFeedbackCellArray> closure_cell_array =
ClosureFeedbackCellArray::New(i_isolate, shared_function);
Handle<FeedbackVector> fv = factory->NewFeedbackVector(
shared_function, closure_cell_array, allocation);
return fv;
}

View File

@ -157,6 +157,7 @@ TEST(VectorICMetadata) {
TEST(VectorCallICStates) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -164,7 +165,8 @@ TEST(VectorCallICStates) {
Isolate* isolate = CcTest::i_isolate();
// Make sure function f has a call that uses a type feedback slot.
CompileRun(
"function foo() { return 17; }"
"function foo() { return 17; };"
"%EnsureFeedbackVectorForFunction(f);"
"function f(a) { a(); } f(foo);");
Handle<JSFunction> f = GetFunction("f");
// There should be one IC.
@ -185,6 +187,7 @@ TEST(VectorCallICStates) {
TEST(VectorCallFeedback) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -193,6 +196,7 @@ TEST(VectorCallFeedback) {
// Make sure function f has a call that uses a type feedback slot.
CompileRun(
"function foo() { return 17; }"
"%EnsureFeedbackVectorForFunction(f);"
"function f(a) { a(); } f(foo);");
Handle<JSFunction> f = GetFunction("f");
Handle<JSFunction> foo = GetFunction("foo");
@ -215,13 +219,17 @@ TEST(VectorCallFeedback) {
TEST(VectorCallFeedbackForArray) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
Isolate* isolate = CcTest::i_isolate();
// Make sure function f has a call that uses a type feedback slot.
CompileRun("function f(a) { a(); } f(Array);");
CompileRun(
"function f(a) { a(); };"
"%EnsureFeedbackVectorForFunction(f);"
"f(Array);");
Handle<JSFunction> f = GetFunction("f");
// There should be one IC.
Handle<FeedbackVector> feedback_vector =
@ -252,6 +260,8 @@ size_t GetFeedbackVectorLength(Isolate* isolate, const char* src,
TEST(OneShotCallICSlotCount) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
if (i::FLAG_lazy_feedback_allocation) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -306,6 +316,7 @@ TEST(OneShotCallICSlotCount) {
TEST(VectorCallCounts) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -315,6 +326,7 @@ TEST(VectorCallCounts) {
// Make sure function f has a call that uses a type feedback slot.
CompileRun(
"function foo() { return 17; }"
"%EnsureFeedbackVectorForFunction(f);"
"function f(a) { a(); } f(foo);");
Handle<JSFunction> f = GetFunction("f");
// There should be one IC.
@ -337,6 +349,7 @@ TEST(VectorCallCounts) {
TEST(VectorConstructCounts) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -346,6 +359,7 @@ TEST(VectorConstructCounts) {
// Make sure function f has a call that uses a type feedback slot.
CompileRun(
"function Foo() {}"
"%EnsureFeedbackVectorForFunction(f);"
"function f(a) { new a(); } f(Foo);");
Handle<JSFunction> f = GetFunction("f");
Handle<FeedbackVector> feedback_vector =
@ -370,6 +384,7 @@ TEST(VectorConstructCounts) {
TEST(VectorSpeculationMode) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -379,6 +394,7 @@ TEST(VectorSpeculationMode) {
// Make sure function f has a call that uses a type feedback slot.
CompileRun(
"function Foo() {}"
"%EnsureFeedbackVectorForFunction(f);"
"function f(a) { new a(); } f(Foo);");
Handle<JSFunction> f = GetFunction("f");
Handle<FeedbackVector> feedback_vector =
@ -404,6 +420,7 @@ TEST(VectorSpeculationMode) {
TEST(VectorLoadICStates) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -413,6 +430,7 @@ TEST(VectorLoadICStates) {
// Make sure function f has a call that uses a type feedback slot.
CompileRun(
"var o = { foo: 3 };"
"%EnsureFeedbackVectorForFunction(f);"
"function f(a) { return a.foo; } f(o);");
Handle<JSFunction> f = GetFunction("f");
// There should be one IC.
@ -459,6 +477,7 @@ TEST(VectorLoadICStates) {
TEST(VectorLoadGlobalICSlotSharing) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -474,6 +493,7 @@ TEST(VectorLoadGlobalICSlotSharing) {
" var y = typeof o;"
" return o , typeof o, x , y, o;"
"}"
"%EnsureFeedbackVectorForFunction(f);"
"f();");
Handle<JSFunction> f = GetFunction("f");
// There should be two IC slots for {o} references outside and inside
@ -494,6 +514,7 @@ TEST(VectorLoadGlobalICSlotSharing) {
TEST(VectorLoadICOnSmi) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -504,6 +525,7 @@ TEST(VectorLoadICOnSmi) {
// Make sure function f has a call that uses a type feedback slot.
CompileRun(
"var o = { foo: 3 };"
"%EnsureFeedbackVectorForFunction(f);"
"function f(a) { return a.foo; } f(o);");
Handle<JSFunction> f = GetFunction("f");
// There should be one IC.
@ -554,6 +576,7 @@ TEST(VectorLoadICOnSmi) {
TEST(ReferenceContextAllocatesNoSlots) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -567,6 +590,7 @@ TEST(ReferenceContextAllocatesNoSlots) {
" y = a;"
" return y;"
"}"
"%EnsureFeedbackVectorForFunction(testvar);"
"a = 3;"
"testvar({});");
@ -588,6 +612,7 @@ TEST(ReferenceContextAllocatesNoSlots) {
" 'use strict';"
" x.blue = a;"
"}"
"%EnsureFeedbackVectorForFunction(testprop);"
"testprop({ blue: 3 });");
Handle<JSFunction> f = GetFunction("testprop");
@ -606,6 +631,7 @@ TEST(ReferenceContextAllocatesNoSlots) {
" x().blue = a;"
" return x().blue;"
"}"
"%EnsureFeedbackVectorForFunction(testpropfunc);"
"function makeresult() { return { blue: 3 }; }"
"testpropfunc(makeresult);");
@ -629,6 +655,7 @@ TEST(ReferenceContextAllocatesNoSlots) {
" x[0] = a;"
" return x[0];"
"}"
"%EnsureFeedbackVectorForFunction(testkeyedprop);"
"testkeyedprop([0, 1, 2]);");
Handle<JSFunction> f = GetFunction("testkeyedprop");
@ -650,6 +677,7 @@ TEST(ReferenceContextAllocatesNoSlots) {
" x[0] = a;"
" return x[0];"
"}"
"%EnsureFeedbackVectorForFunction(testkeyedprop);"
"testkeyedprop([0, 1, 2]);");
Handle<JSFunction> f = GetFunction("testkeyedprop");
@ -671,6 +699,7 @@ TEST(ReferenceContextAllocatesNoSlots) {
" x.old = x.young = x.in_between = a;"
" return x.old + x.young;"
"}"
"%EnsureFeedbackVectorForFunction(testcompound);"
"testcompound({ old: 3, young: 3, in_between: 3 });");
Handle<JSFunction> f = GetFunction("testcompound");
@ -694,6 +723,7 @@ TEST(ReferenceContextAllocatesNoSlots) {
TEST(VectorStoreICBasic) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -702,7 +732,8 @@ TEST(VectorStoreICBasic) {
CompileRun(
"function f(a) {"
" a.foo = 5;"
"}"
"};"
"%EnsureFeedbackVectorForFunction(f);"
"var a = { foo: 3 };"
"f(a);"
"f(a);"
@ -720,6 +751,7 @@ TEST(VectorStoreICBasic) {
TEST(StoreOwnIC) {
if (!i::FLAG_use_ic) return;
if (i::FLAG_always_opt) return;
FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
LocalContext context;
@ -729,6 +761,7 @@ TEST(StoreOwnIC) {
"function f(v) {"
" return {a: 0, b: v, c: 0};"
"}"
"%EnsureFeedbackVectorForFunction(f);"
"f(1);"
"f(2);"
"f(3);");

View File

@ -49,8 +49,8 @@ Handle<FeedbackVector> NewFeedbackVector(Isolate* isolate, Spec* spec) {
// Set the raw feedback metadata to circumvent checks that we are not
// overwriting existing metadata.
shared->set_raw_outer_scope_info_or_feedback_metadata(*metadata);
Handle<FixedArray> closure_feedback_cell_array =
FeedbackVector::NewClosureFeedbackCellArray(isolate, shared);
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array =
ClosureFeedbackCellArray::New(isolate, shared);
return FeedbackVector::New(isolate, shared, closure_feedback_cell_array);
}

View File

@ -3908,7 +3908,10 @@ TEST(WeakReference) {
i::Handle<i::SharedFunctionInfo> shared_function =
i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared(),
i_isolate);
i::Handle<i::FeedbackVector> fv = factory->NewFeedbackVector(shared_function);
i::Handle<i::ClosureFeedbackCellArray> feedback_cell_array =
i::ClosureFeedbackCellArray::New(i_isolate, shared_function);
i::Handle<i::FeedbackVector> fv =
factory->NewFeedbackVector(shared_function, feedback_cell_array);
// Create a Code.
i::Assembler assm(i::AssemblerOptions{});

View File

@ -174,20 +174,25 @@ function make_array() {
return eval(make_array_string());
}
%EnsureFeedbackVectorForFunction(construct_smis);
function construct_smis() {
var a = make_array();
a[0] = 0; // Send the COW array map to the steak house.
assertKind(elements_kind.fast_smi_only, a);
return a;
}
%NeverOptimizeFunction(construct_doubles);
%EnsureFeedbackVectorForFunction(construct_doubles);
function construct_doubles() {
var a = construct_smis();
a[0] = 1.5;
assertKind(elements_kind.fast_double, a);
return a;
}
%NeverOptimizeFunction(construct_objects);
%EnsureFeedbackVectorForFunction(construct_objects);
function construct_objects() {
var a = construct_smis();
a[0] = "one";
@ -196,6 +201,7 @@ function construct_objects() {
}
// Test crankshafted transition SMI->DOUBLE.
%EnsureFeedbackVectorForFunction(convert_to_double);
%NeverOptimizeFunction(convert_to_double);
function convert_to_double(array) {
array[1] = 2.5;
@ -208,6 +214,7 @@ for (var i = 0; i < 3; i++) convert_to_double(smis);
smis = construct_smis();
convert_to_double(smis);
// Test crankshafted transitions SMI->FAST and DOUBLE->FAST.
%EnsureFeedbackVectorForFunction(convert_to_fast);
%NeverOptimizeFunction(convert_to_fast);
function convert_to_fast(array) {
array[1] = "two";
@ -225,7 +232,8 @@ convert_to_fast(smis);
convert_to_fast(doubles);
// Test transition chain SMI->DOUBLE->FAST (crankshafted function will
// transition to FAST directly).
%NeverOptimizeFunction(convert_mixed);
%EnsureFeedbackVectorForFunction(convert_mixed);
%NeverOptimizeFunction(convert_mixed);
function convert_mixed(array, value, kind) {
array[1] = value;
assertKind(kind, array);
@ -267,6 +275,7 @@ function crankshaft_test() {
var c = [get(1), get(2), get(3.5)];
assertKind(elements_kind.fast_double, c);
}
%PrepareFunctionForOptimization(crankshaft_test);
for (var i = 0; i < 3; i++) {
crankshaft_test();
}

View File

@ -100,6 +100,7 @@ function make_array() {
return eval(make_array_string());
}
%EnsureFeedbackVectorForFunction(construct_smis);
function construct_smis() {
var a = make_array();
a[0] = 0; // Send the COW array map to the steak house.
@ -108,6 +109,7 @@ function construct_smis() {
}
%NeverOptimizeFunction(construct_doubles);
%EnsureFeedbackVectorForFunction(construct_doubles);
function construct_doubles() {
var a = construct_smis();
a[0] = 1.5;
@ -116,12 +118,14 @@ function construct_doubles() {
}
%NeverOptimizeFunction(convert_mixed);
%EnsureFeedbackVectorForFunction(convert_mixed);
function convert_mixed(array, value, kind) {
array[1] = value;
assertKind(kind, array);
assertEquals(value, array[1]);
}
%PrepareFunctionForOptimization(test1);
function test1() {
// Test transition chain SMI->DOUBLE->FAST (crankshafted function will
// transition to FAST directly).

View File

@ -87,59 +87,66 @@ function assertKind(expected, obj, name_opt) {
assertEquals(expected, getKind(obj), name_opt);
}
%NeverOptimizeFunction(construct_smis);
%NeverOptimizeFunction(construct_doubles);
%NeverOptimizeFunction(convert_mixed);
for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); }
%EnsureFeedbackVectorForFunction(test_osr_elements_kind);
function test_osr_elements_kind() {
%NeverOptimizeFunction(construct_smis);
%NeverOptimizeFunction(construct_doubles);
%NeverOptimizeFunction(convert_mixed);
for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); }
// This code exists to eliminate the learning influence of AllocationSites
// on the following tests.
var __sequence = 0;
function make_array_string() {
this.__sequence = this.__sequence + 1;
return "/* " + this.__sequence + " */ [0, 0, 0];"
}
function make_array() {
return eval(make_array_string());
}
// This code exists to eliminate the learning influence of AllocationSites
// on the following tests.
var __sequence = 0;
function make_array_string() {
this.__sequence = this.__sequence + 1;
return "/* " + this.__sequence + " */ [0, 0, 0];"
}
function make_array() {
return eval(make_array_string());
}
function construct_smis() {
var a = make_array();
a[0] = 0; // Send the COW array map to the steak house.
assertKind(elements_kind.fast_smi_only, a);
return a;
}
function construct_doubles() {
var a = construct_smis();
a[0] = 1.5;
assertKind(elements_kind.fast_double, a);
return a;
}
%EnsureFeedbackVectorForFunction(construct_smis);
function construct_smis() {
var a = make_array();
a[0] = 0; // Send the COW array map to the steak house.
assertKind(elements_kind.fast_smi_only, a);
return a;
}
// Test transition chain SMI->DOUBLE->FAST (optimized function will
// transition to FAST directly).
function convert_mixed(array, value, kind) {
array[1] = value;
assertKind(kind, array);
assertEquals(value, array[1]);
}
smis = construct_smis();
convert_mixed(smis, 1.5, elements_kind.fast_double);
%EnsureFeedbackVectorForFunction(construct_doubles);
function construct_doubles() {
var a = construct_smis();
a[0] = 1.5;
assertKind(elements_kind.fast_double, a);
return a;
}
doubles = construct_doubles();
convert_mixed(doubles, "three", elements_kind.fast);
convert_mixed(construct_smis(), "three", elements_kind.fast);
convert_mixed(construct_doubles(), "three", elements_kind.fast);
if (%ICsAreEnabled()) {
// Test that allocation sites allocate correct elements kind initially based
// on previous transitions.
// Test transition chain SMI->DOUBLE->FAST (optimized function will
// transition to FAST directly).
%EnsureFeedbackVectorForFunction(convert_mixed);
function convert_mixed(array, value, kind) {
array[1] = value;
assertKind(kind, array);
assertEquals(value, array[1]);
}
smis = construct_smis();
convert_mixed(smis, 1.5, elements_kind.fast_double);
doubles = construct_doubles();
convert_mixed(smis, 1, elements_kind.fast);
convert_mixed(doubles, 1, elements_kind.fast);
assertTrue(%HaveSameMap(smis, doubles));
convert_mixed(doubles, "three", elements_kind.fast);
convert_mixed(construct_smis(), "three", elements_kind.fast);
convert_mixed(construct_doubles(), "three", elements_kind.fast);
if (%ICsAreEnabled()) {
// Test that allocation sites allocate correct elements kind initially based
// on previous transitions.
smis = construct_smis();
doubles = construct_doubles();
convert_mixed(smis, 1, elements_kind.fast);
convert_mixed(doubles, 1, elements_kind.fast);
assertTrue(%HaveSameMap(smis, doubles));
}
}
// Throw away type information in the ICs for next stress run.

View File

@ -108,8 +108,8 @@ class JSCallReducerTest : public TypedGraphTest {
// Set the raw feedback metadata to circumvent checks that we are not
// overwriting existing metadata.
shared->set_raw_outer_scope_info_or_feedback_metadata(*metadata);
Handle<FixedArray> closure_feedback_cell_array =
FeedbackVector::NewClosureFeedbackCellArray(isolate(), shared);
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array =
ClosureFeedbackCellArray::New(isolate(), shared);
Handle<FeedbackVector> vector =
FeedbackVector::New(isolate(), shared, closure_feedback_cell_array);
VectorSlotPair feedback(vector, FeedbackSlot(0), UNINITIALIZED);

View File

@ -35,8 +35,8 @@ class RedundancyEliminationTest : public GraphTest {
isolate()->factory()->NewSharedFunctionInfoForBuiltin(
isolate()->factory()->empty_string(), Builtins::kIllegal);
shared->set_raw_outer_scope_info_or_feedback_metadata(*metadata);
Handle<FixedArray> closure_feedback_cell_array =
FeedbackVector::NewClosureFeedbackCellArray(isolate(), shared);
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array =
ClosureFeedbackCellArray::New(isolate(), shared);
Handle<FeedbackVector> feedback_vector =
FeedbackVector::New(isolate(), shared, closure_feedback_cell_array);
vector_slot_pairs_.push_back(VectorSlotPair());

View File

@ -89,49 +89,50 @@ INSTANCE_TYPES = {
188: "EMBEDDER_DATA_ARRAY_TYPE",
189: "FIXED_ARRAY_TYPE",
190: "OBJECT_BOILERPLATE_DESCRIPTION_TYPE",
191: "HASH_TABLE_TYPE",
192: "ORDERED_HASH_MAP_TYPE",
193: "ORDERED_HASH_SET_TYPE",
194: "ORDERED_NAME_DICTIONARY_TYPE",
195: "NAME_DICTIONARY_TYPE",
196: "GLOBAL_DICTIONARY_TYPE",
197: "NUMBER_DICTIONARY_TYPE",
198: "SIMPLE_NUMBER_DICTIONARY_TYPE",
199: "STRING_TABLE_TYPE",
200: "EPHEMERON_HASH_TABLE_TYPE",
201: "SCOPE_INFO_TYPE",
202: "SCRIPT_CONTEXT_TABLE_TYPE",
203: "AWAIT_CONTEXT_TYPE",
204: "BLOCK_CONTEXT_TYPE",
205: "CATCH_CONTEXT_TYPE",
206: "DEBUG_EVALUATE_CONTEXT_TYPE",
207: "EVAL_CONTEXT_TYPE",
208: "FUNCTION_CONTEXT_TYPE",
209: "MODULE_CONTEXT_TYPE",
210: "NATIVE_CONTEXT_TYPE",
211: "SCRIPT_CONTEXT_TYPE",
212: "WITH_CONTEXT_TYPE",
213: "WEAK_FIXED_ARRAY_TYPE",
214: "TRANSITION_ARRAY_TYPE",
215: "CALL_HANDLER_INFO_TYPE",
216: "CELL_TYPE",
217: "CODE_DATA_CONTAINER_TYPE",
218: "DESCRIPTOR_ARRAY_TYPE",
219: "FEEDBACK_CELL_TYPE",
220: "FEEDBACK_VECTOR_TYPE",
221: "LOAD_HANDLER_TYPE",
222: "PREPARSE_DATA_TYPE",
223: "PROPERTY_ARRAY_TYPE",
224: "PROPERTY_CELL_TYPE",
225: "SHARED_FUNCTION_INFO_TYPE",
226: "SMALL_ORDERED_HASH_MAP_TYPE",
227: "SMALL_ORDERED_HASH_SET_TYPE",
228: "SMALL_ORDERED_NAME_DICTIONARY_TYPE",
229: "STORE_HANDLER_TYPE",
230: "UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE",
231: "UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE",
232: "WEAK_ARRAY_LIST_TYPE",
233: "WEAK_CELL_TYPE",
191: "CLOSURE_FEEDBACK_CELL_ARRAY_TYPE",
192: "HASH_TABLE_TYPE",
193: "ORDERED_HASH_MAP_TYPE",
194: "ORDERED_HASH_SET_TYPE",
195: "ORDERED_NAME_DICTIONARY_TYPE",
196: "NAME_DICTIONARY_TYPE",
197: "GLOBAL_DICTIONARY_TYPE",
198: "NUMBER_DICTIONARY_TYPE",
199: "SIMPLE_NUMBER_DICTIONARY_TYPE",
200: "STRING_TABLE_TYPE",
201: "EPHEMERON_HASH_TABLE_TYPE",
202: "SCOPE_INFO_TYPE",
203: "SCRIPT_CONTEXT_TABLE_TYPE",
204: "AWAIT_CONTEXT_TYPE",
205: "BLOCK_CONTEXT_TYPE",
206: "CATCH_CONTEXT_TYPE",
207: "DEBUG_EVALUATE_CONTEXT_TYPE",
208: "EVAL_CONTEXT_TYPE",
209: "FUNCTION_CONTEXT_TYPE",
210: "MODULE_CONTEXT_TYPE",
211: "NATIVE_CONTEXT_TYPE",
212: "SCRIPT_CONTEXT_TYPE",
213: "WITH_CONTEXT_TYPE",
214: "WEAK_FIXED_ARRAY_TYPE",
215: "TRANSITION_ARRAY_TYPE",
216: "CALL_HANDLER_INFO_TYPE",
217: "CELL_TYPE",
218: "CODE_DATA_CONTAINER_TYPE",
219: "DESCRIPTOR_ARRAY_TYPE",
220: "FEEDBACK_CELL_TYPE",
221: "FEEDBACK_VECTOR_TYPE",
222: "LOAD_HANDLER_TYPE",
223: "PREPARSE_DATA_TYPE",
224: "PROPERTY_ARRAY_TYPE",
225: "PROPERTY_CELL_TYPE",
226: "SHARED_FUNCTION_INFO_TYPE",
227: "SMALL_ORDERED_HASH_MAP_TYPE",
228: "SMALL_ORDERED_HASH_SET_TYPE",
229: "SMALL_ORDERED_NAME_DICTIONARY_TYPE",
230: "STORE_HANDLER_TYPE",
231: "UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE",
232: "UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE",
233: "WEAK_ARRAY_LIST_TYPE",
234: "WEAK_CELL_TYPE",
1024: "JS_PROXY_TYPE",
1025: "JS_GLOBAL_OBJECT_TYPE",
1026: "JS_GLOBAL_PROXY_TYPE",
@ -195,8 +196,8 @@ KNOWN_MAPS = {
("RO_SPACE", 0x00139): (138, "FreeSpaceMap"),
("RO_SPACE", 0x00189): (132, "MetaMap"),
("RO_SPACE", 0x00209): (131, "NullMap"),
("RO_SPACE", 0x00271): (218, "DescriptorArrayMap"),
("RO_SPACE", 0x002d1): (213, "WeakFixedArrayMap"),
("RO_SPACE", 0x00271): (219, "DescriptorArrayMap"),
("RO_SPACE", 0x002d1): (214, "WeakFixedArrayMap"),
("RO_SPACE", 0x00321): (152, "OnePointerFillerMap"),
("RO_SPACE", 0x00371): (152, "TwoPointerFillerMap"),
("RO_SPACE", 0x003f1): (131, "UninitializedMap"),
@ -209,140 +210,141 @@ KNOWN_MAPS = {
("RO_SPACE", 0x007b1): (136, "ByteArrayMap"),
("RO_SPACE", 0x00801): (189, "FixedArrayMap"),
("RO_SPACE", 0x00851): (189, "FixedCOWArrayMap"),
("RO_SPACE", 0x008a1): (191, "HashTableMap"),
("RO_SPACE", 0x008a1): (192, "HashTableMap"),
("RO_SPACE", 0x008f1): (128, "SymbolMap"),
("RO_SPACE", 0x00941): (40, "OneByteStringMap"),
("RO_SPACE", 0x00991): (201, "ScopeInfoMap"),
("RO_SPACE", 0x009e1): (225, "SharedFunctionInfoMap"),
("RO_SPACE", 0x00991): (202, "ScopeInfoMap"),
("RO_SPACE", 0x009e1): (226, "SharedFunctionInfoMap"),
("RO_SPACE", 0x00a31): (133, "CodeMap"),
("RO_SPACE", 0x00a81): (208, "FunctionContextMap"),
("RO_SPACE", 0x00ad1): (216, "CellMap"),
("RO_SPACE", 0x00b21): (224, "GlobalPropertyCellMap"),
("RO_SPACE", 0x00a81): (209, "FunctionContextMap"),
("RO_SPACE", 0x00ad1): (217, "CellMap"),
("RO_SPACE", 0x00b21): (225, "GlobalPropertyCellMap"),
("RO_SPACE", 0x00b71): (135, "ForeignMap"),
("RO_SPACE", 0x00bc1): (214, "TransitionArrayMap"),
("RO_SPACE", 0x00c11): (220, "FeedbackVectorMap"),
("RO_SPACE", 0x00bc1): (215, "TransitionArrayMap"),
("RO_SPACE", 0x00c11): (221, "FeedbackVectorMap"),
("RO_SPACE", 0x00cb1): (131, "ArgumentsMarkerMap"),
("RO_SPACE", 0x00d51): (131, "ExceptionMap"),
("RO_SPACE", 0x00df1): (131, "TerminationExceptionMap"),
("RO_SPACE", 0x00e99): (131, "OptimizedOutMap"),
("RO_SPACE", 0x00f39): (131, "StaleRegisterMap"),
("RO_SPACE", 0x00fa9): (210, "NativeContextMap"),
("RO_SPACE", 0x00ff9): (209, "ModuleContextMap"),
("RO_SPACE", 0x01049): (207, "EvalContextMap"),
("RO_SPACE", 0x01099): (211, "ScriptContextMap"),
("RO_SPACE", 0x010e9): (203, "AwaitContextMap"),
("RO_SPACE", 0x01139): (204, "BlockContextMap"),
("RO_SPACE", 0x01189): (205, "CatchContextMap"),
("RO_SPACE", 0x011d9): (212, "WithContextMap"),
("RO_SPACE", 0x01229): (206, "DebugEvaluateContextMap"),
("RO_SPACE", 0x01279): (202, "ScriptContextTableMap"),
("RO_SPACE", 0x012c9): (151, "FeedbackMetadataArrayMap"),
("RO_SPACE", 0x01319): (189, "ArrayListMap"),
("RO_SPACE", 0x01369): (130, "BigIntMap"),
("RO_SPACE", 0x013b9): (190, "ObjectBoilerplateDescriptionMap"),
("RO_SPACE", 0x01409): (137, "BytecodeArrayMap"),
("RO_SPACE", 0x01459): (217, "CodeDataContainerMap"),
("RO_SPACE", 0x014a9): (150, "FixedDoubleArrayMap"),
("RO_SPACE", 0x014f9): (196, "GlobalDictionaryMap"),
("RO_SPACE", 0x01549): (219, "ManyClosuresCellMap"),
("RO_SPACE", 0x01599): (189, "ModuleInfoMap"),
("RO_SPACE", 0x015e9): (134, "MutableHeapNumberMap"),
("RO_SPACE", 0x01639): (195, "NameDictionaryMap"),
("RO_SPACE", 0x01689): (219, "NoClosuresCellMap"),
("RO_SPACE", 0x016d9): (197, "NumberDictionaryMap"),
("RO_SPACE", 0x01729): (219, "OneClosureCellMap"),
("RO_SPACE", 0x01779): (192, "OrderedHashMapMap"),
("RO_SPACE", 0x017c9): (193, "OrderedHashSetMap"),
("RO_SPACE", 0x01819): (194, "OrderedNameDictionaryMap"),
("RO_SPACE", 0x01869): (222, "PreparseDataMap"),
("RO_SPACE", 0x018b9): (223, "PropertyArrayMap"),
("RO_SPACE", 0x01909): (215, "SideEffectCallHandlerInfoMap"),
("RO_SPACE", 0x01959): (215, "SideEffectFreeCallHandlerInfoMap"),
("RO_SPACE", 0x019a9): (215, "NextCallSideEffectFreeCallHandlerInfoMap"),
("RO_SPACE", 0x019f9): (198, "SimpleNumberDictionaryMap"),
("RO_SPACE", 0x01a49): (189, "SloppyArgumentsElementsMap"),
("RO_SPACE", 0x01a99): (226, "SmallOrderedHashMapMap"),
("RO_SPACE", 0x01ae9): (227, "SmallOrderedHashSetMap"),
("RO_SPACE", 0x01b39): (228, "SmallOrderedNameDictionaryMap"),
("RO_SPACE", 0x01b89): (199, "StringTableMap"),
("RO_SPACE", 0x01bd9): (230, "UncompiledDataWithoutPreparseDataMap"),
("RO_SPACE", 0x01c29): (231, "UncompiledDataWithPreparseDataMap"),
("RO_SPACE", 0x01c79): (232, "WeakArrayListMap"),
("RO_SPACE", 0x01cc9): (200, "EphemeronHashTableMap"),
("RO_SPACE", 0x01d19): (188, "EmbedderDataArrayMap"),
("RO_SPACE", 0x01d69): (233, "WeakCellMap"),
("RO_SPACE", 0x01db9): (58, "NativeSourceStringMap"),
("RO_SPACE", 0x01e09): (32, "StringMap"),
("RO_SPACE", 0x01e59): (41, "ConsOneByteStringMap"),
("RO_SPACE", 0x01ea9): (33, "ConsStringMap"),
("RO_SPACE", 0x01ef9): (45, "ThinOneByteStringMap"),
("RO_SPACE", 0x01f49): (37, "ThinStringMap"),
("RO_SPACE", 0x01f99): (35, "SlicedStringMap"),
("RO_SPACE", 0x01fe9): (43, "SlicedOneByteStringMap"),
("RO_SPACE", 0x02039): (34, "ExternalStringMap"),
("RO_SPACE", 0x02089): (42, "ExternalOneByteStringMap"),
("RO_SPACE", 0x020d9): (50, "UncachedExternalStringMap"),
("RO_SPACE", 0x02129): (0, "InternalizedStringMap"),
("RO_SPACE", 0x02179): (2, "ExternalInternalizedStringMap"),
("RO_SPACE", 0x021c9): (10, "ExternalOneByteInternalizedStringMap"),
("RO_SPACE", 0x02219): (18, "UncachedExternalInternalizedStringMap"),
("RO_SPACE", 0x02269): (26, "UncachedExternalOneByteInternalizedStringMap"),
("RO_SPACE", 0x022b9): (58, "UncachedExternalOneByteStringMap"),
("RO_SPACE", 0x02309): (140, "FixedUint8ArrayMap"),
("RO_SPACE", 0x02359): (139, "FixedInt8ArrayMap"),
("RO_SPACE", 0x023a9): (142, "FixedUint16ArrayMap"),
("RO_SPACE", 0x023f9): (141, "FixedInt16ArrayMap"),
("RO_SPACE", 0x02449): (144, "FixedUint32ArrayMap"),
("RO_SPACE", 0x02499): (143, "FixedInt32ArrayMap"),
("RO_SPACE", 0x024e9): (145, "FixedFloat32ArrayMap"),
("RO_SPACE", 0x02539): (146, "FixedFloat64ArrayMap"),
("RO_SPACE", 0x02589): (147, "FixedUint8ClampedArrayMap"),
("RO_SPACE", 0x025d9): (149, "FixedBigUint64ArrayMap"),
("RO_SPACE", 0x02629): (148, "FixedBigInt64ArrayMap"),
("RO_SPACE", 0x02679): (131, "SelfReferenceMarkerMap"),
("RO_SPACE", 0x026e1): (175, "Tuple2Map"),
("RO_SPACE", 0x02781): (177, "ArrayBoilerplateDescriptionMap"),
("RO_SPACE", 0x02ac1): (164, "InterceptorInfoMap"),
("RO_SPACE", 0x050a9): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x050f9): (154, "AccessorInfoMap"),
("RO_SPACE", 0x05149): (155, "AccessorPairMap"),
("RO_SPACE", 0x05199): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x051e9): (157, "AllocationMementoMap"),
("RO_SPACE", 0x05239): (158, "AsmWasmDataMap"),
("RO_SPACE", 0x05289): (159, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x052d9): (160, "ClassPositionsMap"),
("RO_SPACE", 0x05329): (161, "DebugInfoMap"),
("RO_SPACE", 0x05379): (162, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x053c9): (163, "FunctionTemplateRareDataMap"),
("RO_SPACE", 0x05419): (165, "InterpreterDataMap"),
("RO_SPACE", 0x05469): (166, "ModuleInfoEntryMap"),
("RO_SPACE", 0x054b9): (167, "ModuleMap"),
("RO_SPACE", 0x05509): (168, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x05559): (169, "PromiseCapabilityMap"),
("RO_SPACE", 0x055a9): (170, "PromiseReactionMap"),
("RO_SPACE", 0x055f9): (171, "PrototypeInfoMap"),
("RO_SPACE", 0x05649): (172, "ScriptMap"),
("RO_SPACE", 0x05699): (173, "StackFrameInfoMap"),
("RO_SPACE", 0x056e9): (174, "StackTraceFrameMap"),
("RO_SPACE", 0x05739): (176, "Tuple3Map"),
("RO_SPACE", 0x05789): (178, "WasmDebugInfoMap"),
("RO_SPACE", 0x057d9): (179, "WasmExceptionTagMap"),
("RO_SPACE", 0x05829): (180, "WasmExportedFunctionDataMap"),
("RO_SPACE", 0x05879): (181, "CallableTaskMap"),
("RO_SPACE", 0x058c9): (182, "CallbackTaskMap"),
("RO_SPACE", 0x05919): (183, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x05969): (184, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x059b9): (185, "PromiseResolveThenableJobTaskMap"),
("RO_SPACE", 0x05a09): (186, "FinalizationGroupCleanupJobTaskMap"),
("RO_SPACE", 0x05a59): (187, "AllocationSiteWithWeakNextMap"),
("RO_SPACE", 0x05aa9): (187, "AllocationSiteWithoutWeakNextMap"),
("RO_SPACE", 0x05af9): (221, "LoadHandler1Map"),
("RO_SPACE", 0x05b49): (221, "LoadHandler2Map"),
("RO_SPACE", 0x05b99): (221, "LoadHandler3Map"),
("RO_SPACE", 0x05be9): (229, "StoreHandler0Map"),
("RO_SPACE", 0x05c39): (229, "StoreHandler1Map"),
("RO_SPACE", 0x05c89): (229, "StoreHandler2Map"),
("RO_SPACE", 0x05cd9): (229, "StoreHandler3Map"),
("RO_SPACE", 0x00fa9): (211, "NativeContextMap"),
("RO_SPACE", 0x00ff9): (210, "ModuleContextMap"),
("RO_SPACE", 0x01049): (208, "EvalContextMap"),
("RO_SPACE", 0x01099): (212, "ScriptContextMap"),
("RO_SPACE", 0x010e9): (204, "AwaitContextMap"),
("RO_SPACE", 0x01139): (205, "BlockContextMap"),
("RO_SPACE", 0x01189): (206, "CatchContextMap"),
("RO_SPACE", 0x011d9): (213, "WithContextMap"),
("RO_SPACE", 0x01229): (207, "DebugEvaluateContextMap"),
("RO_SPACE", 0x01279): (203, "ScriptContextTableMap"),
("RO_SPACE", 0x012c9): (191, "ClosureFeedbackCellArrayMap"),
("RO_SPACE", 0x01319): (151, "FeedbackMetadataArrayMap"),
("RO_SPACE", 0x01369): (189, "ArrayListMap"),
("RO_SPACE", 0x013b9): (130, "BigIntMap"),
("RO_SPACE", 0x01409): (190, "ObjectBoilerplateDescriptionMap"),
("RO_SPACE", 0x01459): (137, "BytecodeArrayMap"),
("RO_SPACE", 0x014a9): (218, "CodeDataContainerMap"),
("RO_SPACE", 0x014f9): (150, "FixedDoubleArrayMap"),
("RO_SPACE", 0x01549): (197, "GlobalDictionaryMap"),
("RO_SPACE", 0x01599): (220, "ManyClosuresCellMap"),
("RO_SPACE", 0x015e9): (189, "ModuleInfoMap"),
("RO_SPACE", 0x01639): (134, "MutableHeapNumberMap"),
("RO_SPACE", 0x01689): (196, "NameDictionaryMap"),
("RO_SPACE", 0x016d9): (220, "NoClosuresCellMap"),
("RO_SPACE", 0x01729): (198, "NumberDictionaryMap"),
("RO_SPACE", 0x01779): (220, "OneClosureCellMap"),
("RO_SPACE", 0x017c9): (193, "OrderedHashMapMap"),
("RO_SPACE", 0x01819): (194, "OrderedHashSetMap"),
("RO_SPACE", 0x01869): (195, "OrderedNameDictionaryMap"),
("RO_SPACE", 0x018b9): (223, "PreparseDataMap"),
("RO_SPACE", 0x01909): (224, "PropertyArrayMap"),
("RO_SPACE", 0x01959): (216, "SideEffectCallHandlerInfoMap"),
("RO_SPACE", 0x019a9): (216, "SideEffectFreeCallHandlerInfoMap"),
("RO_SPACE", 0x019f9): (216, "NextCallSideEffectFreeCallHandlerInfoMap"),
("RO_SPACE", 0x01a49): (199, "SimpleNumberDictionaryMap"),
("RO_SPACE", 0x01a99): (189, "SloppyArgumentsElementsMap"),
("RO_SPACE", 0x01ae9): (227, "SmallOrderedHashMapMap"),
("RO_SPACE", 0x01b39): (228, "SmallOrderedHashSetMap"),
("RO_SPACE", 0x01b89): (229, "SmallOrderedNameDictionaryMap"),
("RO_SPACE", 0x01bd9): (200, "StringTableMap"),
("RO_SPACE", 0x01c29): (231, "UncompiledDataWithoutPreparseDataMap"),
("RO_SPACE", 0x01c79): (232, "UncompiledDataWithPreparseDataMap"),
("RO_SPACE", 0x01cc9): (233, "WeakArrayListMap"),
("RO_SPACE", 0x01d19): (201, "EphemeronHashTableMap"),
("RO_SPACE", 0x01d69): (188, "EmbedderDataArrayMap"),
("RO_SPACE", 0x01db9): (234, "WeakCellMap"),
("RO_SPACE", 0x01e09): (58, "NativeSourceStringMap"),
("RO_SPACE", 0x01e59): (32, "StringMap"),
("RO_SPACE", 0x01ea9): (41, "ConsOneByteStringMap"),
("RO_SPACE", 0x01ef9): (33, "ConsStringMap"),
("RO_SPACE", 0x01f49): (45, "ThinOneByteStringMap"),
("RO_SPACE", 0x01f99): (37, "ThinStringMap"),
("RO_SPACE", 0x01fe9): (35, "SlicedStringMap"),
("RO_SPACE", 0x02039): (43, "SlicedOneByteStringMap"),
("RO_SPACE", 0x02089): (34, "ExternalStringMap"),
("RO_SPACE", 0x020d9): (42, "ExternalOneByteStringMap"),
("RO_SPACE", 0x02129): (50, "UncachedExternalStringMap"),
("RO_SPACE", 0x02179): (0, "InternalizedStringMap"),
("RO_SPACE", 0x021c9): (2, "ExternalInternalizedStringMap"),
("RO_SPACE", 0x02219): (10, "ExternalOneByteInternalizedStringMap"),
("RO_SPACE", 0x02269): (18, "UncachedExternalInternalizedStringMap"),
("RO_SPACE", 0x022b9): (26, "UncachedExternalOneByteInternalizedStringMap"),
("RO_SPACE", 0x02309): (58, "UncachedExternalOneByteStringMap"),
("RO_SPACE", 0x02359): (140, "FixedUint8ArrayMap"),
("RO_SPACE", 0x023a9): (139, "FixedInt8ArrayMap"),
("RO_SPACE", 0x023f9): (142, "FixedUint16ArrayMap"),
("RO_SPACE", 0x02449): (141, "FixedInt16ArrayMap"),
("RO_SPACE", 0x02499): (144, "FixedUint32ArrayMap"),
("RO_SPACE", 0x024e9): (143, "FixedInt32ArrayMap"),
("RO_SPACE", 0x02539): (145, "FixedFloat32ArrayMap"),
("RO_SPACE", 0x02589): (146, "FixedFloat64ArrayMap"),
("RO_SPACE", 0x025d9): (147, "FixedUint8ClampedArrayMap"),
("RO_SPACE", 0x02629): (149, "FixedBigUint64ArrayMap"),
("RO_SPACE", 0x02679): (148, "FixedBigInt64ArrayMap"),
("RO_SPACE", 0x026c9): (131, "SelfReferenceMarkerMap"),
("RO_SPACE", 0x02731): (175, "Tuple2Map"),
("RO_SPACE", 0x027d1): (177, "ArrayBoilerplateDescriptionMap"),
("RO_SPACE", 0x02b11): (164, "InterceptorInfoMap"),
("RO_SPACE", 0x050f9): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x05149): (154, "AccessorInfoMap"),
("RO_SPACE", 0x05199): (155, "AccessorPairMap"),
("RO_SPACE", 0x051e9): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x05239): (157, "AllocationMementoMap"),
("RO_SPACE", 0x05289): (158, "AsmWasmDataMap"),
("RO_SPACE", 0x052d9): (159, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x05329): (160, "ClassPositionsMap"),
("RO_SPACE", 0x05379): (161, "DebugInfoMap"),
("RO_SPACE", 0x053c9): (162, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x05419): (163, "FunctionTemplateRareDataMap"),
("RO_SPACE", 0x05469): (165, "InterpreterDataMap"),
("RO_SPACE", 0x054b9): (166, "ModuleInfoEntryMap"),
("RO_SPACE", 0x05509): (167, "ModuleMap"),
("RO_SPACE", 0x05559): (168, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x055a9): (169, "PromiseCapabilityMap"),
("RO_SPACE", 0x055f9): (170, "PromiseReactionMap"),
("RO_SPACE", 0x05649): (171, "PrototypeInfoMap"),
("RO_SPACE", 0x05699): (172, "ScriptMap"),
("RO_SPACE", 0x056e9): (173, "StackFrameInfoMap"),
("RO_SPACE", 0x05739): (174, "StackTraceFrameMap"),
("RO_SPACE", 0x05789): (176, "Tuple3Map"),
("RO_SPACE", 0x057d9): (178, "WasmDebugInfoMap"),
("RO_SPACE", 0x05829): (179, "WasmExceptionTagMap"),
("RO_SPACE", 0x05879): (180, "WasmExportedFunctionDataMap"),
("RO_SPACE", 0x058c9): (181, "CallableTaskMap"),
("RO_SPACE", 0x05919): (182, "CallbackTaskMap"),
("RO_SPACE", 0x05969): (183, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x059b9): (184, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x05a09): (185, "PromiseResolveThenableJobTaskMap"),
("RO_SPACE", 0x05a59): (186, "FinalizationGroupCleanupJobTaskMap"),
("RO_SPACE", 0x05aa9): (187, "AllocationSiteWithWeakNextMap"),
("RO_SPACE", 0x05af9): (187, "AllocationSiteWithoutWeakNextMap"),
("RO_SPACE", 0x05b49): (222, "LoadHandler1Map"),
("RO_SPACE", 0x05b99): (222, "LoadHandler2Map"),
("RO_SPACE", 0x05be9): (222, "LoadHandler3Map"),
("RO_SPACE", 0x05c39): (230, "StoreHandler0Map"),
("RO_SPACE", 0x05c89): (230, "StoreHandler1Map"),
("RO_SPACE", 0x05cd9): (230, "StoreHandler2Map"),
("RO_SPACE", 0x05d29): (230, "StoreHandler3Map"),
("MAP_SPACE", 0x00139): (1057, "ExternalMap"),
("MAP_SPACE", 0x00189): (1073, "JSMessageObjectMap"),
}
@ -367,37 +369,37 @@ KNOWN_OBJECTS = {
("RO_SPACE", 0x00dc1): "TerminationException",
("RO_SPACE", 0x00e69): "OptimizedOut",
("RO_SPACE", 0x00f09): "StaleRegister",
("RO_SPACE", 0x026c9): "EmptyEnumCache",
("RO_SPACE", 0x02731): "EmptyPropertyArray",
("RO_SPACE", 0x02741): "EmptyByteArray",
("RO_SPACE", 0x02751): "EmptyObjectBoilerplateDescription",
("RO_SPACE", 0x02769): "EmptyArrayBoilerplateDescription",
("RO_SPACE", 0x027d1): "EmptyFixedUint8Array",
("RO_SPACE", 0x027f1): "EmptyFixedInt8Array",
("RO_SPACE", 0x02811): "EmptyFixedUint16Array",
("RO_SPACE", 0x02831): "EmptyFixedInt16Array",
("RO_SPACE", 0x02851): "EmptyFixedUint32Array",
("RO_SPACE", 0x02871): "EmptyFixedInt32Array",
("RO_SPACE", 0x02891): "EmptyFixedFloat32Array",
("RO_SPACE", 0x028b1): "EmptyFixedFloat64Array",
("RO_SPACE", 0x028d1): "EmptyFixedUint8ClampedArray",
("RO_SPACE", 0x028f1): "EmptyFixedBigUint64Array",
("RO_SPACE", 0x02911): "EmptyFixedBigInt64Array",
("RO_SPACE", 0x02931): "EmptySloppyArgumentsElements",
("RO_SPACE", 0x02951): "EmptySlowElementDictionary",
("RO_SPACE", 0x02999): "EmptyOrderedHashMap",
("RO_SPACE", 0x029c1): "EmptyOrderedHashSet",
("RO_SPACE", 0x029e9): "EmptyFeedbackMetadata",
("RO_SPACE", 0x029f9): "EmptyPropertyCell",
("RO_SPACE", 0x02a21): "EmptyPropertyDictionary",
("RO_SPACE", 0x02a71): "NoOpInterceptorInfo",
("RO_SPACE", 0x02b11): "EmptyWeakArrayList",
("RO_SPACE", 0x02b29): "InfinityValue",
("RO_SPACE", 0x02b39): "MinusZeroValue",
("RO_SPACE", 0x02b49): "MinusInfinityValue",
("RO_SPACE", 0x02b59): "SelfReferenceMarker",
("RO_SPACE", 0x02bb1): "OffHeapTrampolineRelocationInfo",
("RO_SPACE", 0x02bc9): "HashSeed",
("RO_SPACE", 0x02719): "EmptyEnumCache",
("RO_SPACE", 0x02781): "EmptyPropertyArray",
("RO_SPACE", 0x02791): "EmptyByteArray",
("RO_SPACE", 0x027a1): "EmptyObjectBoilerplateDescription",
("RO_SPACE", 0x027b9): "EmptyArrayBoilerplateDescription",
("RO_SPACE", 0x02821): "EmptyFixedUint8Array",
("RO_SPACE", 0x02841): "EmptyFixedInt8Array",
("RO_SPACE", 0x02861): "EmptyFixedUint16Array",
("RO_SPACE", 0x02881): "EmptyFixedInt16Array",
("RO_SPACE", 0x028a1): "EmptyFixedUint32Array",
("RO_SPACE", 0x028c1): "EmptyFixedInt32Array",
("RO_SPACE", 0x028e1): "EmptyFixedFloat32Array",
("RO_SPACE", 0x02901): "EmptyFixedFloat64Array",
("RO_SPACE", 0x02921): "EmptyFixedUint8ClampedArray",
("RO_SPACE", 0x02941): "EmptyFixedBigUint64Array",
("RO_SPACE", 0x02961): "EmptyFixedBigInt64Array",
("RO_SPACE", 0x02981): "EmptySloppyArgumentsElements",
("RO_SPACE", 0x029a1): "EmptySlowElementDictionary",
("RO_SPACE", 0x029e9): "EmptyOrderedHashMap",
("RO_SPACE", 0x02a11): "EmptyOrderedHashSet",
("RO_SPACE", 0x02a39): "EmptyFeedbackMetadata",
("RO_SPACE", 0x02a49): "EmptyPropertyCell",
("RO_SPACE", 0x02a71): "EmptyPropertyDictionary",
("RO_SPACE", 0x02ac1): "NoOpInterceptorInfo",
("RO_SPACE", 0x02b61): "EmptyWeakArrayList",
("RO_SPACE", 0x02b79): "InfinityValue",
("RO_SPACE", 0x02b89): "MinusZeroValue",
("RO_SPACE", 0x02b99): "MinusInfinityValue",
("RO_SPACE", 0x02ba9): "SelfReferenceMarker",
("RO_SPACE", 0x02c01): "OffHeapTrampolineRelocationInfo",
("RO_SPACE", 0x02c19): "HashSeed",
("OLD_SPACE", 0x00139): "ArgumentsIteratorAccessor",
("OLD_SPACE", 0x001a9): "ArrayLengthAccessor",
("OLD_SPACE", 0x00219): "BoundFunctionLengthAccessor",