Commit 048fe9b9 authored by kasperl@chromium.org's avatar kasperl@chromium.org

RFC: Try to be much more careful with where we skip the write barrier by:

  
  1. Avoid using SKIP_WRITE_BARRIER when we don't have to (smis).
  2. Check and document the remaining uses of SKIP_WRITE_BARRIER.
  3. Only allow GetWriteBarrierMode when in an AssertNoAllocation scope.

The only functional change should be in DeepCopyBoilerplate where we
no longer use the write barrier mode (because of allocations). I'm
running benchmarks to see if this has a measurable impact on performance.
Review URL: http://codereview.chromium.org/558041

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3743 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2498d5cb
...@@ -247,8 +247,10 @@ BUILTIN(ArrayCodeGeneric) { ...@@ -247,8 +247,10 @@ BUILTIN(ArrayCodeGeneric) {
Smi* len = Smi::FromInt(number_of_elements); Smi* len = Smi::FromInt(number_of_elements);
Object* obj = Heap::AllocateFixedArrayWithHoles(len->value()); Object* obj = Heap::AllocateFixedArrayWithHoles(len->value());
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
AssertNoAllocation no_gc;
FixedArray* elms = FixedArray::cast(obj); FixedArray* elms = FixedArray::cast(obj);
WriteBarrierMode mode = elms->GetWriteBarrierMode(); WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
// Fill in the content // Fill in the content
for (int index = 0; index < number_of_elements; index++) { for (int index = 0; index < number_of_elements; index++) {
elms->set(index, args[index+1], mode); elms->set(index, args[index+1], mode);
...@@ -256,7 +258,7 @@ BUILTIN(ArrayCodeGeneric) { ...@@ -256,7 +258,7 @@ BUILTIN(ArrayCodeGeneric) {
// Set length and elements on the array. // Set length and elements on the array.
array->set_elements(FixedArray::cast(obj)); array->set_elements(FixedArray::cast(obj));
array->set_length(len, SKIP_WRITE_BARRIER); array->set_length(len);
return array; return array;
} }
...@@ -283,8 +285,10 @@ BUILTIN(ArrayPush) { ...@@ -283,8 +285,10 @@ BUILTIN(ArrayPush) {
int capacity = new_length + (new_length >> 1) + 16; int capacity = new_length + (new_length >> 1) + 16;
Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
AssertNoAllocation no_gc;
FixedArray* new_elms = FixedArray::cast(obj); FixedArray* new_elms = FixedArray::cast(obj);
WriteBarrierMode mode = new_elms->GetWriteBarrierMode(); WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
// Fill out the new array with old elements. // Fill out the new array with old elements.
for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode); for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
// Add the provided values. // Add the provided values.
...@@ -295,7 +299,7 @@ BUILTIN(ArrayPush) { ...@@ -295,7 +299,7 @@ BUILTIN(ArrayPush) {
array->set_elements(new_elms); array->set_elements(new_elms);
} }
// Set the length. // Set the length.
array->set_length(Smi::FromInt(new_length), SKIP_WRITE_BARRIER); array->set_length(Smi::FromInt(new_length));
return array->length(); return array->length();
} }
...@@ -313,7 +317,7 @@ BUILTIN(ArrayPop) { ...@@ -313,7 +317,7 @@ BUILTIN(ArrayPop) {
Object* top = elms->get(len - 1); Object* top = elms->get(len - 1);
// Set the length. // Set the length.
array->set_length(Smi::FromInt(len - 1), SKIP_WRITE_BARRIER); array->set_length(Smi::FromInt(len - 1));
if (!top->IsTheHole()) { if (!top->IsTheHole()) {
// Delete the top element. // Delete the top element.
......
...@@ -72,15 +72,9 @@ bool DateParser::DayComposer::Write(FixedArray* output) { ...@@ -72,15 +72,9 @@ bool DateParser::DayComposer::Write(FixedArray* output) {
if (!Smi::IsValid(year) || !IsMonth(month) || !IsDay(day)) return false; if (!Smi::IsValid(year) || !IsMonth(month) || !IsDay(day)) return false;
output->set(YEAR, output->set(YEAR, Smi::FromInt(year));
Smi::FromInt(year), output->set(MONTH, Smi::FromInt(month - 1)); // 0-based
SKIP_WRITE_BARRIER); output->set(DAY, Smi::FromInt(day));
output->set(MONTH,
Smi::FromInt(month - 1),
SKIP_WRITE_BARRIER); // 0-based
output->set(DAY,
Smi::FromInt(day),
SKIP_WRITE_BARRIER);
return true; return true;
} }
...@@ -103,15 +97,9 @@ bool DateParser::TimeComposer::Write(FixedArray* output) { ...@@ -103,15 +97,9 @@ bool DateParser::TimeComposer::Write(FixedArray* output) {
if (!IsHour(hour) || !IsMinute(minute) || !IsSecond(second)) return false; if (!IsHour(hour) || !IsMinute(minute) || !IsSecond(second)) return false;
output->set(HOUR, output->set(HOUR, Smi::FromInt(hour));
Smi::FromInt(hour), output->set(MINUTE, Smi::FromInt(minute));
SKIP_WRITE_BARRIER); output->set(SECOND, Smi::FromInt(second));
output->set(MINUTE,
Smi::FromInt(minute),
SKIP_WRITE_BARRIER);
output->set(SECOND,
Smi::FromInt(second),
SKIP_WRITE_BARRIER);
return true; return true;
} }
...@@ -121,13 +109,9 @@ bool DateParser::TimeZoneComposer::Write(FixedArray* output) { ...@@ -121,13 +109,9 @@ bool DateParser::TimeZoneComposer::Write(FixedArray* output) {
if (minute_ == kNone) minute_ = 0; if (minute_ == kNone) minute_ = 0;
int total_seconds = sign_ * (hour_ * 3600 + minute_ * 60); int total_seconds = sign_ * (hour_ * 3600 + minute_ * 60);
if (!Smi::IsValid(total_seconds)) return false; if (!Smi::IsValid(total_seconds)) return false;
output->set(UTC_OFFSET, output->set(UTC_OFFSET, Smi::FromInt(total_seconds));
Smi::FromInt(total_seconds),
SKIP_WRITE_BARRIER);
} else { } else {
output->set(UTC_OFFSET, output->set_null(UTC_OFFSET);
Heap::null_value(),
SKIP_WRITE_BARRIER);
} }
return true; return true;
} }
......
...@@ -204,6 +204,7 @@ class AccessorInfo; ...@@ -204,6 +204,7 @@ class AccessorInfo;
class Allocation; class Allocation;
class Arguments; class Arguments;
class Assembler; class Assembler;
class AssertNoAllocation;
class BreakableStatement; class BreakableStatement;
class Code; class Code;
class CodeGenerator; class CodeGenerator;
......
...@@ -1729,7 +1729,7 @@ void Heap::SetNumberStringCache(Object* number, String* string) { ...@@ -1729,7 +1729,7 @@ void Heap::SetNumberStringCache(Object* number, String* string) {
int mask = (number_string_cache()->length() >> 1) - 1; int mask = (number_string_cache()->length() >> 1) - 1;
if (number->IsSmi()) { if (number->IsSmi()) {
hash = smi_get_hash(Smi::cast(number)) & mask; hash = smi_get_hash(Smi::cast(number)) & mask;
number_string_cache()->set(hash * 2, number, SKIP_WRITE_BARRIER); number_string_cache()->set(hash * 2, Smi::cast(number));
} else { } else {
hash = double_get_hash(number->Number()) & mask; hash = double_get_hash(number->Number()) & mask;
number_string_cache()->set(hash * 2, number); number_string_cache()->set(hash * 2, number);
...@@ -1986,8 +1986,10 @@ Object* Heap::AllocateConsString(String* first, String* second) { ...@@ -1986,8 +1986,10 @@ Object* Heap::AllocateConsString(String* first, String* second) {
Object* result = Allocate(map, NEW_SPACE); Object* result = Allocate(map, NEW_SPACE);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
AssertNoAllocation no_gc;
ConsString* cons_string = ConsString::cast(result); ConsString* cons_string = ConsString::cast(result);
WriteBarrierMode mode = cons_string->GetWriteBarrierMode(); WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc);
cons_string->set_length(length); cons_string->set_length(length);
cons_string->set_hash_field(String::kEmptyHashField); cons_string->set_hash_field(String::kEmptyHashField);
cons_string->set_first(first, mode); cons_string->set_first(first, mode);
...@@ -2285,7 +2287,7 @@ Object* Heap::InitializeFunction(JSFunction* function, ...@@ -2285,7 +2287,7 @@ Object* Heap::InitializeFunction(JSFunction* function,
function->set_shared(shared); function->set_shared(shared);
function->set_prototype_or_initial_map(prototype); function->set_prototype_or_initial_map(prototype);
function->set_context(undefined_value()); function->set_context(undefined_value());
function->set_literals(empty_fixed_array(), SKIP_WRITE_BARRIER); function->set_literals(empty_fixed_array());
return function; return function;
} }
...@@ -2886,8 +2888,10 @@ Object* Heap::CopyFixedArray(FixedArray* src) { ...@@ -2886,8 +2888,10 @@ Object* Heap::CopyFixedArray(FixedArray* src) {
HeapObject::cast(obj)->set_map(src->map()); HeapObject::cast(obj)->set_map(src->map());
FixedArray* result = FixedArray::cast(obj); FixedArray* result = FixedArray::cast(obj);
result->set_length(len); result->set_length(len);
// Copy the content // Copy the content
WriteBarrierMode mode = result->GetWriteBarrierMode(); AssertNoAllocation no_gc;
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
for (int i = 0; i < len; i++) result->set(i, src->get(i), mode); for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
return result; return result;
} }
...@@ -2905,6 +2909,7 @@ Object* Heap::AllocateFixedArray(int length) { ...@@ -2905,6 +2909,7 @@ Object* Heap::AllocateFixedArray(int length) {
Object* value = undefined_value(); Object* value = undefined_value();
// Initialize body. // Initialize body.
for (int index = 0; index < length; index++) { for (int index = 0; index < length; index++) {
ASSERT(!Heap::InNewSpace(value)); // value = undefined
array->set(index, value, SKIP_WRITE_BARRIER); array->set(index, value, SKIP_WRITE_BARRIER);
} }
} }
...@@ -2960,6 +2965,7 @@ Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { ...@@ -2960,6 +2965,7 @@ Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
array->set_length(length); array->set_length(length);
Object* value = undefined_value(); Object* value = undefined_value();
for (int index = 0; index < length; index++) { for (int index = 0; index < length; index++) {
ASSERT(!Heap::InNewSpace(value)); // value = undefined
array->set(index, value, SKIP_WRITE_BARRIER); array->set(index, value, SKIP_WRITE_BARRIER);
} }
return array; return array;
...@@ -2977,6 +2983,7 @@ Object* Heap::AllocateFixedArrayWithHoles(int length) { ...@@ -2977,6 +2983,7 @@ Object* Heap::AllocateFixedArrayWithHoles(int length) {
// Initialize body. // Initialize body.
Object* value = the_hole_value(); Object* value = the_hole_value();
for (int index = 0; index < length; index++) { for (int index = 0; index < length; index++) {
ASSERT(!Heap::InNewSpace(value)); // value = the hole
array->set(index, value, SKIP_WRITE_BARRIER); array->set(index, value, SKIP_WRITE_BARRIER);
} }
} }
......
...@@ -1349,7 +1349,7 @@ void FixedArray::set(int index, Object* value) { ...@@ -1349,7 +1349,7 @@ void FixedArray::set(int index, Object* value) {
} }
WriteBarrierMode HeapObject::GetWriteBarrierMode() { WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER; if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
return UPDATE_WRITE_BARRIER; return UPDATE_WRITE_BARRIER;
} }
...@@ -1548,9 +1548,7 @@ uint32_t NumberDictionary::max_number_key() { ...@@ -1548,9 +1548,7 @@ uint32_t NumberDictionary::max_number_key() {
} }
void NumberDictionary::set_requires_slow_elements() { void NumberDictionary::set_requires_slow_elements() {
set(kMaxNumberKeyIndex, set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
Smi::FromInt(kRequiresSlowElementsMask),
SKIP_WRITE_BARRIER);
} }
...@@ -2973,7 +2971,8 @@ void Dictionary<Shape, Key>::SetEntry(int entry, ...@@ -2973,7 +2971,8 @@ void Dictionary<Shape, Key>::SetEntry(int entry,
PropertyDetails details) { PropertyDetails details) {
ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0); ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
int index = HashTable<Shape, Key>::EntryToIndex(entry); int index = HashTable<Shape, Key>::EntryToIndex(entry);
WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(); AssertNoAllocation no_gc;
WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
FixedArray::set(index, key, mode); FixedArray::set(index, key, mode);
FixedArray::set(index+1, value, mode); FixedArray::set(index+1, value, mode);
FixedArray::fast_set(this, index+2, details.AsSmi()); FixedArray::fast_set(this, index+2, details.AsSmi());
...@@ -3007,8 +3006,13 @@ void JSArray::EnsureSize(int required_size) { ...@@ -3007,8 +3006,13 @@ void JSArray::EnsureSize(int required_size) {
} }
void JSArray::set_length(Smi* length) {
set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
}
void JSArray::SetContent(FixedArray* storage) { void JSArray::SetContent(FixedArray* storage) {
set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER); set_length(Smi::FromInt(storage->length()));
set_elements(storage); set_elements(storage);
} }
......
...@@ -3200,8 +3200,9 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) { ...@@ -3200,8 +3200,9 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) {
Object* obj = Heap::AllocateFixedArray(len0 + extra); Object* obj = Heap::AllocateFixedArray(len0 + extra);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
// Fill in the content // Fill in the content
AssertNoAllocation no_gc;
FixedArray* result = FixedArray::cast(obj); FixedArray* result = FixedArray::cast(obj);
WriteBarrierMode mode = result->GetWriteBarrierMode(); WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
for (int i = 0; i < len0; i++) { for (int i = 0; i < len0; i++) {
result->set(i, get(i), mode); result->set(i, get(i), mode);
} }
...@@ -3225,10 +3226,11 @@ Object* FixedArray::CopySize(int new_length) { ...@@ -3225,10 +3226,11 @@ Object* FixedArray::CopySize(int new_length) {
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
FixedArray* result = FixedArray::cast(obj); FixedArray* result = FixedArray::cast(obj);
// Copy the content // Copy the content
AssertNoAllocation no_gc;
int len = length(); int len = length();
if (new_length < len) len = new_length; if (new_length < len) len = new_length;
result->set_map(map()); result->set_map(map());
WriteBarrierMode mode = result->GetWriteBarrierMode(); WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
result->set(i, get(i), mode); result->set(i, get(i), mode);
} }
...@@ -3237,7 +3239,8 @@ Object* FixedArray::CopySize(int new_length) { ...@@ -3237,7 +3239,8 @@ Object* FixedArray::CopySize(int new_length) {
void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
WriteBarrierMode mode = dest->GetWriteBarrierMode(); AssertNoAllocation no_gc;
WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
for (int index = 0; index < len; index++) { for (int index = 0; index < len; index++) {
dest->set(dest_pos+index, get(pos+index), mode); dest->set(dest_pos+index, get(pos+index), mode);
} }
...@@ -3271,8 +3274,7 @@ Object* DescriptorArray::Allocate(int number_of_descriptors) { ...@@ -3271,8 +3274,7 @@ Object* DescriptorArray::Allocate(int number_of_descriptors) {
if (array->IsFailure()) return array; if (array->IsFailure()) return array;
result->set(kContentArrayIndex, array); result->set(kContentArrayIndex, array);
result->set(kEnumerationIndexIndex, result->set(kEnumerationIndexIndex,
Smi::FromInt(PropertyDetails::kInitialIndex), Smi::FromInt(PropertyDetails::kInitialIndex));
SKIP_WRITE_BARRIER);
return result; return result;
} }
...@@ -4700,8 +4702,8 @@ void Map::ClearNonLiveTransitions(Object* real_prototype) { ...@@ -4700,8 +4702,8 @@ void Map::ClearNonLiveTransitions(Object* real_prototype) {
ASSERT(target->IsHeapObject()); ASSERT(target->IsHeapObject());
if (!target->IsMarked()) { if (!target->IsMarked()) {
ASSERT(target->IsMap()); ASSERT(target->IsMap());
contents->set(i + 1, NullDescriptorDetails, SKIP_WRITE_BARRIER); contents->set(i + 1, NullDescriptorDetails);
contents->set(i, Heap::null_value(), SKIP_WRITE_BARRIER); contents->set_null(i);
ASSERT(target->prototype() == this || ASSERT(target->prototype() == this ||
target->prototype() == real_prototype); target->prototype() == real_prototype);
// Getter prototype() is read-only, set_prototype() has side effects. // Getter prototype() is read-only, set_prototype() has side effects.
...@@ -5161,7 +5163,8 @@ void JSObject::SetFastElements(FixedArray* elems) { ...@@ -5161,7 +5163,8 @@ void JSObject::SetFastElements(FixedArray* elems) {
uint32_t len = static_cast<uint32_t>(elems->length()); uint32_t len = static_cast<uint32_t>(elems->length());
for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole()); for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole());
#endif #endif
WriteBarrierMode mode = elems->GetWriteBarrierMode(); AssertNoAllocation no_gc;
WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
switch (GetElementsKind()) { switch (GetElementsKind()) {
case FAST_ELEMENTS: { case FAST_ELEMENTS: {
FixedArray* old_elements = FixedArray::cast(elements()); FixedArray* old_elements = FixedArray::cast(elements());
...@@ -5228,7 +5231,7 @@ Object* JSObject::SetSlowElements(Object* len) { ...@@ -5228,7 +5231,7 @@ Object* JSObject::SetSlowElements(Object* len) {
Object* JSArray::Initialize(int capacity) { Object* JSArray::Initialize(int capacity) {
ASSERT(capacity >= 0); ASSERT(capacity >= 0);
set_length(Smi::FromInt(0), SKIP_WRITE_BARRIER); set_length(Smi::FromInt(0));
FixedArray* new_elements; FixedArray* new_elements;
if (capacity == 0) { if (capacity == 0) {
new_elements = Heap::empty_fixed_array(); new_elements = Heap::empty_fixed_array();
...@@ -5288,7 +5291,7 @@ Object* JSObject::SetElementsLength(Object* len) { ...@@ -5288,7 +5291,7 @@ Object* JSObject::SetElementsLength(Object* len) {
for (int i = value; i < old_length; i++) { for (int i = value; i < old_length; i++) {
FixedArray::cast(elements())->set_the_hole(i); FixedArray::cast(elements())->set_the_hole(i);
} }
JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); JSArray::cast(this)->set_length(Smi::cast(smi_length));
} }
return this; return this;
} }
...@@ -5298,8 +5301,9 @@ Object* JSObject::SetElementsLength(Object* len) { ...@@ -5298,8 +5301,9 @@ Object* JSObject::SetElementsLength(Object* len) {
!ShouldConvertToSlowElements(new_capacity)) { !ShouldConvertToSlowElements(new_capacity)) {
Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
if (IsJSArray()) JSArray::cast(this)->set_length(smi_length, if (IsJSArray()) {
SKIP_WRITE_BARRIER); JSArray::cast(this)->set_length(Smi::cast(smi_length));
}
SetFastElements(FixedArray::cast(obj)); SetFastElements(FixedArray::cast(obj));
return this; return this;
} }
...@@ -5318,7 +5322,7 @@ Object* JSObject::SetElementsLength(Object* len) { ...@@ -5318,7 +5322,7 @@ Object* JSObject::SetElementsLength(Object* len) {
static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
element_dictionary()->RemoveNumberEntries(value, old_length); element_dictionary()->RemoveNumberEntries(value, old_length);
} }
JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); JSArray::cast(this)->set_length(Smi::cast(smi_length));
} }
return this; return this;
} }
...@@ -5343,8 +5347,7 @@ Object* JSObject::SetElementsLength(Object* len) { ...@@ -5343,8 +5347,7 @@ Object* JSObject::SetElementsLength(Object* len) {
Object* obj = Heap::AllocateFixedArray(1); Object* obj = Heap::AllocateFixedArray(1);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
FixedArray::cast(obj)->set(0, len); FixedArray::cast(obj)->set(0, len);
if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1), if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1));
SKIP_WRITE_BARRIER);
set_elements(FixedArray::cast(obj)); set_elements(FixedArray::cast(obj));
return this; return this;
} }
...@@ -5614,8 +5617,7 @@ Object* JSObject::SetFastElement(uint32_t index, Object* value) { ...@@ -5614,8 +5617,7 @@ Object* JSObject::SetFastElement(uint32_t index, Object* value) {
CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), CHECK(Array::IndexFromObject(JSArray::cast(this)->length(),
&array_length)); &array_length));
if (index >= array_length) { if (index >= array_length) {
JSArray::cast(this)->set_length(Smi::FromInt(index + 1), JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
SKIP_WRITE_BARRIER);
} }
} }
return value; return value;
...@@ -5631,8 +5633,9 @@ Object* JSObject::SetFastElement(uint32_t index, Object* value) { ...@@ -5631,8 +5633,9 @@ Object* JSObject::SetFastElement(uint32_t index, Object* value) {
Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
SetFastElements(FixedArray::cast(obj)); SetFastElements(FixedArray::cast(obj));
if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(index + 1), if (IsJSArray()) {
SKIP_WRITE_BARRIER); JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
}
FixedArray::cast(elements())->set(index, value); FixedArray::cast(elements())->set(index, value);
return value; return value;
} }
...@@ -6129,7 +6132,8 @@ template<typename Shape, typename Key> ...@@ -6129,7 +6132,8 @@ template<typename Shape, typename Key>
void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) { void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
int pos = 0; int pos = 0;
int capacity = HashTable<Shape, Key>::Capacity(); int capacity = HashTable<Shape, Key>::Capacity();
WriteBarrierMode mode = elements->GetWriteBarrierMode(); AssertNoAllocation no_gc;
WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
Object* k = Dictionary<Shape, Key>::KeyAt(i); Object* k = Dictionary<Shape, Key>::KeyAt(i);
if (Dictionary<Shape, Key>::IsKey(k)) { if (Dictionary<Shape, Key>::IsKey(k)) {
...@@ -6500,7 +6504,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage, ...@@ -6500,7 +6504,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
if (storage != NULL) { if (storage != NULL) {
storage->set(counter, Smi::FromInt(i), SKIP_WRITE_BARRIER); storage->set(counter, Smi::FromInt(i));
} }
counter++; counter++;
} }
...@@ -6512,7 +6516,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage, ...@@ -6512,7 +6516,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
int length = PixelArray::cast(elements())->length(); int length = PixelArray::cast(elements())->length();
while (counter < length) { while (counter < length) {
if (storage != NULL) { if (storage != NULL) {
storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER); storage->set(counter, Smi::FromInt(counter));
} }
counter++; counter++;
} }
...@@ -6529,7 +6533,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage, ...@@ -6529,7 +6533,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
int length = ExternalArray::cast(elements())->length(); int length = ExternalArray::cast(elements())->length();
while (counter < length) { while (counter < length) {
if (storage != NULL) { if (storage != NULL) {
storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER); storage->set(counter, Smi::FromInt(counter));
} }
counter++; counter++;
} }
...@@ -6554,7 +6558,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage, ...@@ -6554,7 +6558,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
String* str = String::cast(val); String* str = String::cast(val);
if (storage) { if (storage) {
for (int i = 0; i < str->length(); i++) { for (int i = 0; i < str->length(); i++) {
storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER); storage->set(counter + i, Smi::FromInt(i));
} }
} }
counter += str->length(); counter += str->length();
...@@ -6886,8 +6890,10 @@ Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { ...@@ -6886,8 +6890,10 @@ Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
Object* obj = Allocate(nof * 2); Object* obj = Allocate(nof * 2);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
AssertNoAllocation no_gc;
HashTable* table = HashTable::cast(obj); HashTable* table = HashTable::cast(obj);
WriteBarrierMode mode = table->GetWriteBarrierMode(); WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc);
// Copy prefix to new array. // Copy prefix to new array.
for (int i = kPrefixStartIndex; for (int i = kPrefixStartIndex;
...@@ -7134,7 +7140,7 @@ Object* JSObject::PrepareElementsForSort(uint32_t limit) { ...@@ -7134,7 +7140,7 @@ Object* JSObject::PrepareElementsForSort(uint32_t limit) {
// Split elements into defined, undefined and the_hole, in that order. // Split elements into defined, undefined and the_hole, in that order.
// Only count locations for undefined and the hole, and fill them afterwards. // Only count locations for undefined and the hole, and fill them afterwards.
WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(); WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc);
unsigned int undefs = limit; unsigned int undefs = limit;
unsigned int holes = limit; unsigned int holes = limit;
// Assume most arrays contain no holes and undefined values, so minimize the // Assume most arrays contain no holes and undefined values, so minimize the
...@@ -7629,7 +7635,7 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { ...@@ -7629,7 +7635,7 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
FixedArray* iteration_order = FixedArray::cast(obj); FixedArray* iteration_order = FixedArray::cast(obj);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
iteration_order->set(i, Smi::FromInt(i), SKIP_WRITE_BARRIER); iteration_order->set(i, Smi::FromInt(i));
} }
// Allocate array with enumeration order. // Allocate array with enumeration order.
...@@ -7642,9 +7648,7 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { ...@@ -7642,9 +7648,7 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
int pos = 0; int pos = 0;
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
enumeration_order->set(pos++, enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index()));
Smi::FromInt(DetailsAt(i).index()),
SKIP_WRITE_BARRIER);
} }
} }
...@@ -7655,9 +7659,7 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { ...@@ -7655,9 +7659,7 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
int index = Smi::cast(iteration_order->get(i))->value(); int index = Smi::cast(iteration_order->get(i))->value();
int enum_index = PropertyDetails::kInitialIndex + i; int enum_index = PropertyDetails::kInitialIndex + i;
enumeration_order->set(index, enumeration_order->set(index, Smi::FromInt(enum_index));
Smi::FromInt(enum_index),
SKIP_WRITE_BARRIER);
} }
// Update the dictionary with new indices. // Update the dictionary with new indices.
...@@ -7805,8 +7807,7 @@ void NumberDictionary::UpdateMaxNumberKey(uint32_t key) { ...@@ -7805,8 +7807,7 @@ void NumberDictionary::UpdateMaxNumberKey(uint32_t key) {
Object* max_index_object = get(kMaxNumberKeyIndex); Object* max_index_object = get(kMaxNumberKeyIndex);
if (!max_index_object->IsSmi() || max_number_key() < key) { if (!max_index_object->IsSmi() || max_number_key() < key) {
FixedArray::set(kMaxNumberKeyIndex, FixedArray::set(kMaxNumberKeyIndex,
Smi::FromInt(key << kRequiresSlowElementsTagSize), Smi::FromInt(key << kRequiresSlowElementsTagSize));
SKIP_WRITE_BARRIER);
} }
} }
...@@ -7897,9 +7898,7 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage, ...@@ -7897,9 +7898,7 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
PropertyDetails details = DetailsAt(i); PropertyDetails details = DetailsAt(i);
if (details.IsDeleted() || details.IsDontEnum()) continue; if (details.IsDeleted() || details.IsDontEnum()) continue;
storage->set(index, k); storage->set(index, k);
sort_array->set(index, sort_array->set(index, Smi::FromInt(details.index()));
Smi::FromInt(details.index()),
SKIP_WRITE_BARRIER);
index++; index++;
} }
} }
......
...@@ -1023,8 +1023,12 @@ class HeapObject: public Object { ...@@ -1023,8 +1023,12 @@ class HeapObject: public Object {
// Casting. // Casting.
static inline HeapObject* cast(Object* obj); static inline HeapObject* cast(Object* obj);
// Return the write barrier mode for this. // Return the write barrier mode for this. Callers of this function
inline WriteBarrierMode GetWriteBarrierMode(); // must be able to present a reference to an AssertNoAllocation
// object as a sign that they are not going to use this function
// from code that allocates and thus invalidates the returned write
// barrier mode.
inline WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation&);
// Dispatched behavior. // Dispatched behavior.
void HeapObjectShortPrint(StringStream* accumulator); void HeapObjectShortPrint(StringStream* accumulator);
...@@ -4475,6 +4479,10 @@ class JSArray: public JSObject { ...@@ -4475,6 +4479,10 @@ class JSArray: public JSObject {
// [length]: The length property. // [length]: The length property.
DECL_ACCESSORS(length, Object) DECL_ACCESSORS(length, Object)
// Overload the length setter to skip write barrier when the length
// is set to a smi. This matches the set function on FixedArray.
inline void set_length(Smi* length);
Object* JSArrayUpdateLengthFromIndex(uint32_t index, Object* value); Object* JSArrayUpdateLengthFromIndex(uint32_t index, Object* value);
// Initialize the array with the given capacity. The function may // Initialize the array with the given capacity. The function may
......
...@@ -107,25 +107,23 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) { ...@@ -107,25 +107,23 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
// Deep copy local properties. // Deep copy local properties.
if (copy->HasFastProperties()) { if (copy->HasFastProperties()) {
FixedArray* properties = copy->properties(); FixedArray* properties = copy->properties();
WriteBarrierMode mode = properties->GetWriteBarrierMode();
for (int i = 0; i < properties->length(); i++) { for (int i = 0; i < properties->length(); i++) {
Object* value = properties->get(i); Object* value = properties->get(i);
if (value->IsJSObject()) { if (value->IsJSObject()) {
JSObject* jsObject = JSObject::cast(value); JSObject* js_object = JSObject::cast(value);
result = DeepCopyBoilerplate(jsObject); result = DeepCopyBoilerplate(js_object);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
properties->set(i, result, mode); properties->set(i, result);
} }
} }
mode = copy->GetWriteBarrierMode();
int nof = copy->map()->inobject_properties(); int nof = copy->map()->inobject_properties();
for (int i = 0; i < nof; i++) { for (int i = 0; i < nof; i++) {
Object* value = copy->InObjectPropertyAt(i); Object* value = copy->InObjectPropertyAt(i);
if (value->IsJSObject()) { if (value->IsJSObject()) {
JSObject* jsObject = JSObject::cast(value); JSObject* js_object = JSObject::cast(value);
result = DeepCopyBoilerplate(jsObject); result = DeepCopyBoilerplate(js_object);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
copy->InObjectPropertyAtPut(i, result, mode); copy->InObjectPropertyAtPut(i, result);
} }
} }
} else { } else {
...@@ -135,20 +133,20 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) { ...@@ -135,20 +133,20 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
copy->GetLocalPropertyNames(names, 0); copy->GetLocalPropertyNames(names, 0);
for (int i = 0; i < names->length(); i++) { for (int i = 0; i < names->length(); i++) {
ASSERT(names->get(i)->IsString()); ASSERT(names->get(i)->IsString());
String* keyString = String::cast(names->get(i)); String* key_string = String::cast(names->get(i));
PropertyAttributes attributes = PropertyAttributes attributes =
copy->GetLocalPropertyAttribute(keyString); copy->GetLocalPropertyAttribute(key_string);
// Only deep copy fields from the object literal expression. // Only deep copy fields from the object literal expression.
// In particular, don't try to copy the length attribute of // In particular, don't try to copy the length attribute of
// an array. // an array.
if (attributes != NONE) continue; if (attributes != NONE) continue;
Object* value = copy->GetProperty(keyString, &attributes); Object* value = copy->GetProperty(key_string, &attributes);
ASSERT(!value->IsFailure()); ASSERT(!value->IsFailure());
if (value->IsJSObject()) { if (value->IsJSObject()) {
JSObject* jsObject = JSObject::cast(value); JSObject* js_object = JSObject::cast(value);
result = DeepCopyBoilerplate(jsObject); result = DeepCopyBoilerplate(js_object);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
result = copy->SetProperty(keyString, result, NONE); result = copy->SetProperty(key_string, result, NONE);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
} }
} }
...@@ -160,14 +158,13 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) { ...@@ -160,14 +158,13 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
switch (copy->GetElementsKind()) { switch (copy->GetElementsKind()) {
case JSObject::FAST_ELEMENTS: { case JSObject::FAST_ELEMENTS: {
FixedArray* elements = FixedArray::cast(copy->elements()); FixedArray* elements = FixedArray::cast(copy->elements());
WriteBarrierMode mode = elements->GetWriteBarrierMode();
for (int i = 0; i < elements->length(); i++) { for (int i = 0; i < elements->length(); i++) {
Object* value = elements->get(i); Object* value = elements->get(i);
if (value->IsJSObject()) { if (value->IsJSObject()) {
JSObject* jsObject = JSObject::cast(value); JSObject* js_object = JSObject::cast(value);
result = DeepCopyBoilerplate(jsObject); result = DeepCopyBoilerplate(js_object);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
elements->set(i, result, mode); elements->set(i, result);
} }
} }
break; break;
...@@ -180,8 +177,8 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) { ...@@ -180,8 +177,8 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
if (element_dictionary->IsKey(k)) { if (element_dictionary->IsKey(k)) {
Object* value = element_dictionary->ValueAt(i); Object* value = element_dictionary->ValueAt(i);
if (value->IsJSObject()) { if (value->IsJSObject()) {
JSObject* jsObject = JSObject::cast(value); JSObject* js_object = JSObject::cast(value);
result = DeepCopyBoilerplate(jsObject); result = DeepCopyBoilerplate(js_object);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
element_dictionary->ValueAtPut(i, result); element_dictionary->ValueAtPut(i, result);
} }
...@@ -1439,6 +1436,8 @@ static Object* Runtime_SetCode(Arguments args) { ...@@ -1439,6 +1436,8 @@ static Object* Runtime_SetCode(Arguments args) {
literals->set(JSFunction::kLiteralGlobalContextIndex, literals->set(JSFunction::kLiteralGlobalContextIndex,
context->global_context()); context->global_context());
} }
// It's okay to skip the write barrier here because the literals
// are guaranteed to be in old space.
target->set_literals(*literals, SKIP_WRITE_BARRIER); target->set_literals(*literals, SKIP_WRITE_BARRIER);
} }
...@@ -4717,7 +4716,9 @@ static Object* Runtime_NewArguments(Arguments args) { ...@@ -4717,7 +4716,9 @@ static Object* Runtime_NewArguments(Arguments args) {
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
FixedArray* array = FixedArray::cast(obj); FixedArray* array = FixedArray::cast(obj);
ASSERT(array->length() == length); ASSERT(array->length() == length);
WriteBarrierMode mode = array->GetWriteBarrierMode();
AssertNoAllocation no_gc;
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
array->set(i, frame->GetParameter(i), mode); array->set(i, frame->GetParameter(i), mode);
} }
...@@ -4742,10 +4743,13 @@ static Object* Runtime_NewArgumentsFast(Arguments args) { ...@@ -4742,10 +4743,13 @@ static Object* Runtime_NewArgumentsFast(Arguments args) {
// Allocate the fixed array. // Allocate the fixed array.
Object* obj = Heap::AllocateRawFixedArray(length); Object* obj = Heap::AllocateRawFixedArray(length);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
AssertNoAllocation no_gc;
reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map()); reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map());
FixedArray* array = FixedArray::cast(obj); FixedArray* array = FixedArray::cast(obj);
array->set_length(length); array->set_length(length);
WriteBarrierMode mode = array->GetWriteBarrierMode();
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
array->set(i, *--parameters, mode); array->set(i, *--parameters, mode);
} }
...@@ -6030,7 +6034,7 @@ static Object* Runtime_MoveArrayContents(Arguments args) { ...@@ -6030,7 +6034,7 @@ static Object* Runtime_MoveArrayContents(Arguments args) {
to->SetContent(FixedArray::cast(from->elements())); to->SetContent(FixedArray::cast(from->elements()));
to->set_length(from->length()); to->set_length(from->length());
from->SetContent(Heap::empty_fixed_array()); from->SetContent(Heap::empty_fixed_array());
from->set_length(0); from->set_length(Smi::FromInt(0));
return to; return to;
} }
...@@ -6073,9 +6077,7 @@ static Object* Runtime_GetArrayKeys(Arguments args) { ...@@ -6073,9 +6077,7 @@ static Object* Runtime_GetArrayKeys(Arguments args) {
} else { } else {
Handle<FixedArray> single_interval = Factory::NewFixedArray(2); Handle<FixedArray> single_interval = Factory::NewFixedArray(2);
// -1 means start of array. // -1 means start of array.
single_interval->set(0, single_interval->set(0, Smi::FromInt(-1));
Smi::FromInt(-1),
SKIP_WRITE_BARRIER);
uint32_t actual_length = static_cast<uint32_t>(array->elements()->length()); uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
uint32_t min_length = actual_length < length ? actual_length : length; uint32_t min_length = actual_length < length ? actual_length : length;
Handle<Object> length_object = Handle<Object> length_object =
...@@ -7448,7 +7450,9 @@ static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame, ...@@ -7448,7 +7450,9 @@ static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
const int length = frame->GetProvidedParametersCount(); const int length = frame->GetProvidedParametersCount();
Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length); Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
Handle<FixedArray> array = Factory::NewFixedArray(length); Handle<FixedArray> array = Factory::NewFixedArray(length);
WriteBarrierMode mode = array->GetWriteBarrierMode();
AssertNoAllocation no_gc;
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
array->set(i, frame->GetParameter(i), mode); array->set(i, frame->GetParameter(i), mode);
} }
...@@ -8032,7 +8036,7 @@ static Object* Runtime_CollectStackTrace(Arguments args) { ...@@ -8032,7 +8036,7 @@ static Object* Runtime_CollectStackTrace(Arguments args) {
if (cursor + 2 < elements->length()) { if (cursor + 2 < elements->length()) {
elements->set(cursor++, recv); elements->set(cursor++, recv);
elements->set(cursor++, fun); elements->set(cursor++, fun);
elements->set(cursor++, offset, SKIP_WRITE_BARRIER); elements->set(cursor++, offset);
} else { } else {
HandleScope scope; HandleScope scope;
Handle<Object> recv_handle(recv); Handle<Object> recv_handle(recv);
...@@ -8045,8 +8049,7 @@ static Object* Runtime_CollectStackTrace(Arguments args) { ...@@ -8045,8 +8049,7 @@ static Object* Runtime_CollectStackTrace(Arguments args) {
iter.Advance(); iter.Advance();
} }
result->set_length(Smi::FromInt(cursor), SKIP_WRITE_BARRIER); result->set_length(Smi::FromInt(cursor));
return *result; return *result;
} }
......
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