HValue* receiver_map = AddLoadMap(receiver, nullptr);
HValue* start =
keyed_load ? graph()->GetConstant1() : graph()->GetConstant0();
- HValue* array_map = Add<HLoadKeyed>(array, start, nullptr, FAST_ELEMENTS,
+ HValue* weak_cell = Add<HLoadKeyed>(array, start, nullptr, FAST_ELEMENTS,
ALLOW_RETURN_HOLE);
+ // Load the weak cell value. It may be Smi(0), or a map. Compare nonetheless
+ // against the receiver_map.
+ HValue* array_map = Add<HLoadNamedField>(weak_cell, nullptr,
+ HObjectAccess::ForWeakCellValue());
+
IfBuilder if_correct_map(this);
if_correct_map.If<HCompareObjectEqAndBranch>(receiver_map, array_map);
if_correct_map.Then();
start = keyed_load ? constant_three : constant_two;
HValue* key = builder.BeginBody(start, length, Token::LT);
{
- HValue* array_map = Add<HLoadKeyed>(array, key, nullptr, FAST_ELEMENTS,
+ HValue* weak_cell = Add<HLoadKeyed>(array, key, nullptr, FAST_ELEMENTS,
ALLOW_RETURN_HOLE);
+ HValue* array_map = Add<HLoadNamedField>(
+ weak_cell, nullptr, HObjectAccess::ForWeakCellValue());
IfBuilder if_correct_poly_map(this);
if_correct_poly_map.If<HCompareObjectEqAndBranch>(receiver_map,
array_map);
void FeedbackNexus::InstallHandlers(int start_index, TypeHandleList* types,
CodeHandleList* handlers) {
Isolate* isolate = GetIsolate();
- FixedArray* array = FixedArray::cast(GetFeedback());
+ Handle<FixedArray> array = handle(FixedArray::cast(GetFeedback()), isolate);
int receiver_count = types->length();
for (int current = 0; current < receiver_count; ++current) {
Handle<HeapType> type = types->at(current);
Handle<Map> map = IC::TypeToMap(*type, isolate);
- array->set(start_index + (current * 2), *map);
+ Handle<WeakCell> cell = Map::WeakCellForMap(map);
+ array->set(start_index + (current * 2), *cell);
array->set(start_index + (current * 2 + 1), *handlers->at(current));
}
}
} else if (feedback == *vector()->PremonomorphicSentinel(isolate)) {
return PREMONOMORPHIC;
} else if (feedback->IsFixedArray()) {
+ // Determine state purely by our structure, don't check if the maps are
+ // cleared.
FixedArray* array = FixedArray::cast(feedback);
int length = array->length();
DCHECK(length >= 2);
} else if (feedback == *vector()->GenericSentinel(isolate)) {
return GENERIC;
} else if (feedback->IsFixedArray()) {
+ // Determine state purely by our structure, don't check if the maps are
+ // cleared.
FixedArray* array = FixedArray::cast(feedback);
int length = array->length();
DCHECK(length >= 3);
Handle<Code> handler) {
Handle<FixedArray> array = EnsureArrayOfSize(2);
Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate());
- array->set(0, *receiver_map);
+ Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+ array->set(0, *cell);
array->set(1, *handler);
}
} else {
array->set(0, *name);
}
- array->set(1, *receiver_map);
+ Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+ array->set(1, *cell);
array->set(2, *handler);
}
Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback();
if (feedback->IsFixedArray()) {
+ int found = 0;
FixedArray* array = FixedArray::cast(feedback);
// The array should be of the form [<optional name>], then
// [map, handler, map, handler, ... ]
DCHECK(array->length() >= (2 + start_index));
for (int i = start_index; i < array->length(); i += 2) {
- Map* map = Map::cast(array->get(i));
- maps->Add(handle(map, isolate));
+ WeakCell* cell = WeakCell::cast(array->get(i));
+ if (!cell->cleared()) {
+ Map* map = Map::cast(cell->value());
+ maps->Add(handle(map, isolate));
+ found++;
+ }
}
- return (array->length() - start_index) / 2;
+ return found;
}
return 0;
if (feedback->IsFixedArray()) {
FixedArray* array = FixedArray::cast(feedback);
for (int i = start_index; i < array->length(); i += 2) {
- Map* array_map = Map::cast(array->get(i));
- if (array_map == *map) {
- Code* code = Code::cast(array->get(i + 1));
- DCHECK(code->kind() == Code::HANDLER);
- return handle(code);
+ WeakCell* cell = WeakCell::cast(array->get(i));
+ if (!cell->cleared()) {
+ Map* array_map = Map::cast(cell->value());
+ if (array_map == *map) {
+ Code* code = Code::cast(array->get(i + 1));
+ DCHECK(code->kind() == Code::HANDLER);
+ return handle(code);
+ }
}
}
}
if (feedback->IsFixedArray()) {
FixedArray* array = FixedArray::cast(feedback);
// The array should be of the form [<optional name>], then
- // [map, handler, map, handler, ... ]
+ // [map, handler, map, handler, ... ]. Be sure to skip handlers whose maps
+ // have been cleared.
DCHECK(array->length() >= (2 + start_index));
for (int i = start_index; i < array->length(); i += 2) {
- Code* code = Code::cast(array->get(i + 1));
- DCHECK(code->kind() == Code::HANDLER);
- code_list->Add(handle(code));
- count++;
+ WeakCell* cell = WeakCell::cast(array->get(i));
+ if (!cell->cleared()) {
+ Code* code = Code::cast(array->get(i + 1));
+ DCHECK(code->kind() == Code::HANDLER);
+ code_list->Add(handle(code));
+ count++;
+ }
}
}
return count == length;
TEST(IncrementalMarkingPreservesMonomorphicIC) {
if (i::FLAG_always_opt) return;
- // TODO(mvstanton): vector-ics need to treat maps weakly.
- if (i::FLAG_vector_ics) return;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
i::FLAG_stress_compaction = false;
i::FLAG_allow_natives_syntax = true;
i::FLAG_flush_code_incrementally = true;
- // TODO(mvstanton): vector ics need weak support.
- if (i::FLAG_vector_ics) return;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
TEST(EnsureAllocationSiteDependentCodesProcessed) {
- // TODO(mvstanton): vector ics need weak support!
- if (FLAG_vector_ics) return;
if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
i::FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
}
- // TODO(mvstanton): this test fails when FLAG_vector_ics is true because
- // monomorphic load ics are preserved, but also strongly walked. They
- // end up keeping function bar alive.
-
// The site still exists because of our global handle, but the code is no
// longer referred to by dependent_code().
DependentCode::GroupStartIndexes starts(site->dependent_code());
TEST(CellsInOptimizedCodeAreWeak) {
if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
- // TODO(mvstanton): vector-ics need to treat maps weakly.
- if (i::FLAG_vector_ics) return;
i::FLAG_weak_embedded_objects_in_optimized_code = true;
i::FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
TEST(ObjectsInOptimizedCodeAreWeak) {
- // TODO(mvstanton): vector ics need weak support!
- if (FLAG_vector_ics) return;
if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
i::FLAG_weak_embedded_objects_in_optimized_code = true;
i::FLAG_allow_natives_syntax = true;
TEST(NoWeakHashTableLeakWithIncrementalMarking) {
if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
if (!i::FLAG_incremental_marking) return;
- // TODO(mvstanton): vector ics need weak support.
- if (FLAG_vector_ics) return;
i::FLAG_weak_embedded_objects_in_optimized_code = true;
i::FLAG_allow_natives_syntax = true;
i::FLAG_compilation_cache = false;
// 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) {
- // TODO(mvstanton): vector ics need weak support!
- if (FLAG_vector_ics) return;
CheckWeakness("function loadIC(obj) {"
" return obj.name;"
"}"
TEST(WeakMapInPolymorphicLoadIC) {
- // TODO(mvstanton): vector-ics need to treat maps weakly.
- if (i::FLAG_vector_ics) return;
CheckWeakness(
"function loadIC(obj) {"
" return obj.name;"
TEST(WeakMapInMonomorphicKeyedLoadIC) {
- // TODO(mvstanton): vector ics need weak support!
- if (FLAG_vector_ics) return;
CheckWeakness("function keyedLoadIC(obj, field) {"
" return obj[field];"
"}"