diff options
Diffstat (limited to 'v8/src/objects.cc')
-rw-r--r-- | v8/src/objects.cc | 157 |
1 files changed, 89 insertions, 68 deletions
diff --git a/v8/src/objects.cc b/v8/src/objects.cc index 6806829..3273291 100644 --- a/v8/src/objects.cc +++ b/v8/src/objects.cc @@ -43,22 +43,6 @@ namespace v8 { namespace internal { -#define FIELD_ADDR(p, offset) \ - (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag) - - -#define WRITE_FIELD(p, offset, value) \ - (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value) - - -#define WRITE_INT_FIELD(p, offset, value) \ - (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value) - - -#define WRITE_BARRIER(object, offset) \ - Heap::RecordWrite(object->address(), offset); - - // Getters and setters are stored in a fixed array property. These are // constants for their indices. const int kGetterIndex = 0; @@ -679,7 +663,7 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) { SmartPointer<uc16> smart_chars = this->ToWideCString(); ASSERT(memcmp(*smart_chars, resource->data(), - resource->length()*sizeof(**smart_chars)) == 0); + resource->length() * sizeof(**smart_chars)) == 0); } #endif // DEBUG @@ -3301,6 +3285,13 @@ Vector<const uc16> String::ToUC16Vector() { } ASSERT(string_tag == kExternalStringTag); ExternalTwoByteString* ext = ExternalTwoByteString::cast(string); + // This is a workaround for Chromium bug 9746: http://crbug.com/9746 + // For external strings with a deleted resource we return a special + // Vector which will not compare to any string when doing SymbolTable + // lookups. + if (ext->resource() == NULL) { + return Vector<const uc16>(NULL, length); + } const uc16* start = reinterpret_cast<const uc16*>(ext->resource()->data()); return Vector<const uc16>(start + offset, length); @@ -3602,7 +3593,7 @@ void ExternalTwoByteString::ExternalTwoByteStringReadBlockIntoBuffer( while (chars_read < max_chars) { uint16_t c = data[offset]; if (c <= kMaxAsciiCharCode) { - // Fast case for ASCII characters. Cursor is an input output argument. + // Fast case for ASCII characters. Cursor is an input output argument. if (!unibrow::CharacterStream::EncodeAsciiCharacter(c, rbb->util_buffer, rbb->capacity, @@ -4117,6 +4108,18 @@ static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) { } +// This is a workaround for Chromium bug 9746: http://crbug.com/9746 +// Returns true if this Vector matches the problem exposed in the bug. +template <typename T> +static bool CheckVectorForBug9746(Vector<T> vec) { + // The problem is that somehow external string entries in the symbol + // table can have their resources collected while they are still in the + // table. This should not happen according to the test in the function + // DisposeExternalString in api.cc, but we have evidence that it does. + return (vec.start() == NULL) ? true : false; +} + + static StringInputBuffer string_compare_buffer_b; @@ -4127,7 +4130,9 @@ static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { VectorIterator<char> ib(b->ToAsciiVector()); return CompareStringContents(ia, &ib); } else { - VectorIterator<uc16> ib(b->ToUC16Vector()); + Vector<const uc16> vb = b->ToUC16Vector(); + if (CheckVectorForBug9746(vb)) return false; + VectorIterator<uc16> ib(vb); return CompareStringContents(ia, &ib); } } else { @@ -4169,7 +4174,9 @@ bool String::SlowEquals(String* other) { return CompareRawStringContents(vec1, vec2); } else { VectorIterator<char> buf1(vec1); - VectorIterator<uc16> ib(other->ToUC16Vector()); + Vector<const uc16> vec2 = other->ToUC16Vector(); + if (CheckVectorForBug9746(vec2)) return false; + VectorIterator<uc16> ib(vec2); return CompareStringContents(&buf1, &ib); } } else { @@ -4179,13 +4186,15 @@ bool String::SlowEquals(String* other) { } } else { Vector<const uc16> vec1 = this->ToUC16Vector(); + if (CheckVectorForBug9746(vec1)) return false; if (other->IsFlat()) { if (StringShape(other).IsAsciiRepresentation()) { VectorIterator<uc16> buf1(vec1); VectorIterator<char> ib(other->ToAsciiVector()); return CompareStringContents(&buf1, &ib); } else { - Vector<const uc16> vec2(other->ToUC16Vector()); + Vector<const uc16> vec2 = other->ToUC16Vector(); + if (CheckVectorForBug9746(vec2)) return false; return CompareRawStringContents(vec1, vec2); } } else { @@ -4230,6 +4239,18 @@ bool String::MarkAsUndetectable() { bool String::IsEqualTo(Vector<const char> str) { + // This is a workaround for Chromium bug 9746: http://crbug.com/9746 + // The problem is that somehow external string entries in the symbol + // table can have their resources deleted while they are still in the + // table. This should not happen according to the test in the function + // DisposeExternalString in api.cc but we have evidence that it does. + // Thus we add this bailout here. + StringShape shape(this); + if (shape.IsExternalTwoByte()) { + ExternalTwoByteString* ext = ExternalTwoByteString::cast(this); + if (ext->resource() == NULL) return false; + } + int slen = length(); Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder()); decoder->Reset(str.start(), str.length()); @@ -4604,7 +4625,7 @@ void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator, void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) { IteratePointers(v, kNameOffset, kCodeOffset + kPointerSize); IteratePointers(v, kInstanceClassNameOffset, kScriptOffset + kPointerSize); - IteratePointer(v, kDebugInfoOffset); + IteratePointers(v, kDebugInfoOffset, kInferredNameOffset + kPointerSize); } @@ -5100,7 +5121,7 @@ bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) { VMState state(EXTERNAL); result = getter(index, info); } - if (!result.IsEmpty()) return !result->IsUndefined(); + if (!result.IsEmpty()) return true; } return holder_handle->HasElementPostInterceptor(*receiver_handle, index); } @@ -5827,43 +5848,46 @@ int JSObject::NumberOfEnumProperties() { } -void FixedArray::Swap(int i, int j) { +void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { Object* temp = get(i); set(i, get(j)); set(j, temp); + if (this != numbers) { + temp = numbers->get(i); + numbers->set(i, numbers->get(j)); + numbers->set(j, temp); + } } -static void InsertionSortPairs(FixedArray* content, FixedArray* smis) { - int len = smis->length(); +static void InsertionSortPairs(FixedArray* content, + FixedArray* numbers, + int len) { for (int i = 1; i < len; i++) { int j = i; while (j > 0 && - Smi::cast(smis->get(j-1))->value() > - Smi::cast(smis->get(j))->value()) { - smis->Swap(j-1, j); - content->Swap(j-1, j); + (NumberToUint32(numbers->get(j - 1)) > + NumberToUint32(numbers->get(j)))) { + content->SwapPairs(numbers, j - 1, j); j--; } } } -void HeapSortPairs(FixedArray* content, FixedArray* smis) { +void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) { // In-place heap sort. - ASSERT(content->length() == smis->length()); - int len = smis->length(); + ASSERT(content->length() == numbers->length()); // Bottom-up max-heap construction. for (int i = 1; i < len; ++i) { int child_index = i; while (child_index > 0) { int parent_index = ((child_index + 1) >> 1) - 1; - int parent_value = Smi::cast(smis->get(parent_index))->value(); - int child_value = Smi::cast(smis->get(child_index))->value(); + uint32_t parent_value = NumberToUint32(numbers->get(parent_index)); + uint32_t child_value = NumberToUint32(numbers->get(child_index)); if (parent_value < child_value) { - content->Swap(parent_index, child_index); - smis->Swap(parent_index, child_index); + content->SwapPairs(numbers, parent_index, child_index); } else { break; } @@ -5874,25 +5898,22 @@ void HeapSortPairs(FixedArray* content, FixedArray* smis) { // Extract elements and create sorted array. for (int i = len - 1; i > 0; --i) { // Put max element at the back of the array. - content->Swap(0, i); - smis->Swap(0, i); + content->SwapPairs(numbers, 0, i); // Sift down the new top element. int parent_index = 0; while (true) { int child_index = ((parent_index + 1) << 1) - 1; if (child_index >= i) break; - uint32_t child1_value = Smi::cast(smis->get(child_index))->value(); - uint32_t child2_value = Smi::cast(smis->get(child_index + 1))->value(); - uint32_t parent_value = Smi::cast(smis->get(parent_index))->value(); + uint32_t child1_value = NumberToUint32(numbers->get(child_index)); + uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1)); + uint32_t parent_value = NumberToUint32(numbers->get(parent_index)); if (child_index + 1 >= i || child1_value > child2_value) { if (parent_value > child1_value) break; - content->Swap(parent_index, child_index); - smis->Swap(parent_index, child_index); + content->SwapPairs(numbers, parent_index, child_index); parent_index = child_index; } else { if (parent_value > child2_value) break; - content->Swap(parent_index, child_index + 1); - smis->Swap(parent_index, child_index + 1); + content->SwapPairs(numbers, parent_index, child_index + 1); parent_index = child_index + 1; } } @@ -5900,43 +5921,41 @@ void HeapSortPairs(FixedArray* content, FixedArray* smis) { } -// Sort this array and the smis as pairs wrt. the (distinct) smis. -void FixedArray::SortPairs(FixedArray* smis) { - ASSERT(this->length() == smis->length()); - int len = smis->length(); +// Sort this array and the numbers as pairs wrt. the (distinct) numbers. +void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) { + ASSERT(this->length() == numbers->length()); // For small arrays, simply use insertion sort. if (len <= 10) { - InsertionSortPairs(this, smis); + InsertionSortPairs(this, numbers, len); return; } // Check the range of indices. - int min_index = Smi::cast(smis->get(0))->value(); - int max_index = min_index; - int i; + uint32_t min_index = NumberToUint32(numbers->get(0)); + uint32_t max_index = min_index; + uint32_t i; for (i = 1; i < len; i++) { - if (Smi::cast(smis->get(i))->value() < min_index) { - min_index = Smi::cast(smis->get(i))->value(); - } else if (Smi::cast(smis->get(i))->value() > max_index) { - max_index = Smi::cast(smis->get(i))->value(); + if (NumberToUint32(numbers->get(i)) < min_index) { + min_index = NumberToUint32(numbers->get(i)); + } else if (NumberToUint32(numbers->get(i)) > max_index) { + max_index = NumberToUint32(numbers->get(i)); } } if (max_index - min_index + 1 == len) { // Indices form a contiguous range, unless there are duplicates. - // Do an in-place linear time sort assuming distinct smis, but + // Do an in-place linear time sort assuming distinct numbers, but // avoid hanging in case they are not. for (i = 0; i < len; i++) { - int p; - int j = 0; + uint32_t p; + uint32_t j = 0; // While the current element at i is not at its correct position p, // swap the elements at these two positions. - while ((p = Smi::cast(smis->get(i))->value() - min_index) != i && + while ((p = NumberToUint32(numbers->get(i)) - min_index) != i && j++ < len) { - this->Swap(i, p); - smis->Swap(i, p); + SwapPairs(numbers, i, p); } } } else { - HeapSortPairs(this, smis); + HeapSortPairs(this, numbers, len); return; } } @@ -6267,7 +6286,7 @@ class SymbolKey : public HashTableKey { if (StringShape(string_).IsCons()) { ConsString* cons_string = ConsString::cast(string_); cons_string->TryFlatten(); - if (cons_string->second() == Heap::empty_string()) { + if (cons_string->second()->length() == 0) { string_ = cons_string->first(); } } @@ -6275,6 +6294,7 @@ class SymbolKey : public HashTableKey { Map* map = Heap::SymbolMapForString(string_); if (map != NULL) { string_->set_map(map); + ASSERT(string_->IsSymbol()); return string_; } // Otherwise allocate a new symbol. @@ -6723,7 +6743,7 @@ Object* Dictionary::GenerateNewEnumerationIndices() { } // Sort the arrays wrt. enumeration order. - iteration_order->SortPairs(enumeration_order); + iteration_order->SortPairs(enumeration_order, enumeration_order->length()); // Overwrite the enumeration_order with the enumeration indices. for (int i = 0; i < length; i++) { @@ -6975,6 +6995,7 @@ void Dictionary::CopyKeysTo(FixedArray* storage, PropertyAttributes filter) { if ((attr & filter) == 0) storage->set(index++, k); } } + storage->SortPairs(storage, index); ASSERT(storage->length() >= index); } @@ -6996,7 +7017,7 @@ void Dictionary::CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array) { } } } - storage->SortPairs(sort_array); + storage->SortPairs(sort_array, sort_array->length()); ASSERT(storage->length() >= index); } |