summaryrefslogtreecommitdiffstats
path: root/v8/src/objects.cc
diff options
context:
space:
mode:
Diffstat (limited to 'v8/src/objects.cc')
-rw-r--r--v8/src/objects.cc157
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);
}