Index: src/objects-inl.h |
=================================================================== |
--- src/objects-inl.h (revision 7267) |
+++ src/objects-inl.h (working copy) |
@@ -40,6 +40,7 @@ |
#include "conversions-inl.h" |
#include "heap.h" |
#include "memory.h" |
+#include "isolate.h" |
#include "property.h" |
#include "spaces.h" |
@@ -78,10 +79,19 @@ |
type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \ |
void holder::set_##name(type* value, WriteBarrierMode mode) { \ |
WRITE_FIELD(this, offset, value); \ |
- CONDITIONAL_WRITE_BARRIER(this, offset, mode); \ |
+ CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode); \ |
} |
+// GC-safe accessors do not use HeapObject::GetHeap(), but access TLS instead. |
+#define ACCESSORS_GCSAFE(holder, name, type, offset) \ |
+ type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \ |
+ void holder::set_##name(type* value, WriteBarrierMode mode) { \ |
+ WRITE_FIELD(this, offset, value); \ |
+ CONDITIONAL_WRITE_BARRIER(HEAP, this, offset, mode); \ |
+ } |
+ |
+ |
#define SMI_ACCESSORS(holder, name, offset) \ |
int holder::name() { \ |
Object* value = READ_FIELD(this, offset); \ |
@@ -419,7 +429,7 @@ |
bool MaybeObject::IsTheHole() { |
- return this == Heap::the_hole_value(); |
+ return !IsFailure() && ToObjectUnchecked()->IsTheHole(); |
} |
@@ -487,22 +497,27 @@ |
bool Object::IsContext() { |
- return Object::IsHeapObject() |
- && (HeapObject::cast(this)->map() == Heap::context_map() || |
- HeapObject::cast(this)->map() == Heap::catch_context_map() || |
- HeapObject::cast(this)->map() == Heap::global_context_map()); |
+ if (Object::IsHeapObject()) { |
+ Heap* heap = HeapObject::cast(this)->GetHeap(); |
+ return (HeapObject::cast(this)->map() == heap->context_map() || |
+ HeapObject::cast(this)->map() == heap->catch_context_map() || |
+ HeapObject::cast(this)->map() == heap->global_context_map()); |
+ } |
+ return false; |
} |
bool Object::IsCatchContext() { |
- return Object::IsHeapObject() |
- && HeapObject::cast(this)->map() == Heap::catch_context_map(); |
+ return Object::IsHeapObject() && |
+ HeapObject::cast(this)->map() == |
+ HeapObject::cast(this)->GetHeap()->catch_context_map(); |
} |
bool Object::IsGlobalContext() { |
- return Object::IsHeapObject() |
- && HeapObject::cast(this)->map() == Heap::global_context_map(); |
+ return Object::IsHeapObject() && |
+ HeapObject::cast(this)->map() == |
+ HeapObject::cast(this)->GetHeap()->global_context_map(); |
} |
@@ -524,6 +539,7 @@ |
bool Object::IsOddball() { |
+ ASSERT(HEAP->is_safe_to_read_maps()); |
return Object::IsHeapObject() |
&& HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE; |
} |
@@ -568,7 +584,8 @@ |
bool Object::IsBoolean() { |
- return IsTrue() || IsFalse(); |
+ return IsOddball() && |
+ ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0); |
} |
@@ -590,18 +607,21 @@ |
bool Object::IsHashTable() { |
- return Object::IsHeapObject() |
- && HeapObject::cast(this)->map() == Heap::hash_table_map(); |
+ return Object::IsHeapObject() && |
+ HeapObject::cast(this)->map() == |
+ HeapObject::cast(this)->GetHeap()->hash_table_map(); |
} |
bool Object::IsDictionary() { |
- return IsHashTable() && this != Heap::symbol_table(); |
+ return IsHashTable() && this != |
+ HeapObject::cast(this)->GetHeap()->symbol_table(); |
} |
bool Object::IsSymbolTable() { |
- return IsHashTable() && this == Heap::raw_unchecked_symbol_table(); |
+ return IsHashTable() && this == |
+ HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table(); |
} |
@@ -718,27 +738,32 @@ |
bool Object::IsUndefined() { |
- return this == Heap::undefined_value(); |
+ return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined; |
} |
bool Object::IsNull() { |
- return this == Heap::null_value(); |
+ return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull; |
} |
+bool Object::IsTheHole() { |
+ return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole; |
+} |
+ |
+ |
bool Object::IsTrue() { |
- return this == Heap::true_value(); |
+ return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue; |
} |
bool Object::IsFalse() { |
- return this == Heap::false_value(); |
+ return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse; |
} |
bool Object::IsArgumentsMarker() { |
- return this == Heap::arguments_marker(); |
+ return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker; |
} |
@@ -750,7 +775,6 @@ |
} |
- |
MaybeObject* Object::ToSmi() { |
if (IsSmi()) return this; |
if (IsHeapNumber()) { |
@@ -773,7 +797,7 @@ |
// GetElement can trigger a getter which can cause allocation. |
// This was not always the case. This ASSERT is here to catch |
// leftover incorrect uses. |
- ASSERT(Heap::IsAllocationAllowed()); |
+ ASSERT(HEAP->IsAllocationAllowed()); |
return GetElementWithReceiver(this, index); |
} |
@@ -807,19 +831,19 @@ |
#define WRITE_FIELD(p, offset, value) \ |
(*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value) |
- |
+// TODO(isolates): Pass heap in to these macros. |
#define WRITE_BARRIER(object, offset) \ |
- Heap::RecordWrite(object->address(), offset); |
+ object->GetHeap()->RecordWrite(object->address(), offset); |
// CONDITIONAL_WRITE_BARRIER must be issued after the actual |
// write due to the assert validating the written value. |
-#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \ |
+#define CONDITIONAL_WRITE_BARRIER(heap, object, offset, mode) \ |
if (mode == UPDATE_WRITE_BARRIER) { \ |
- Heap::RecordWrite(object->address(), offset); \ |
+ heap->RecordWrite(object->address(), offset); \ |
} else { \ |
ASSERT(mode == SKIP_WRITE_BARRIER); \ |
- ASSERT(Heap::InNewSpace(object) || \ |
- !Heap::InNewSpace(READ_FIELD(object, offset)) || \ |
+ ASSERT(heap->InNewSpace(object) || \ |
+ !heap->InNewSpace(READ_FIELD(object, offset)) || \ |
Page::FromAddress(object->address())-> \ |
IsRegionDirty(object->address() + offset)); \ |
} |
@@ -1099,6 +1123,23 @@ |
#endif |
+Heap* HeapObject::GetHeap() { |
+ // During GC, the map pointer in HeapObject is used in various ways that |
+ // prevent us from retrieving Heap from the map. |
+ // Assert that we are not in GC, implement GC code in a way that it doesn't |
+ // pull heap from the map. |
+ ASSERT(HEAP->is_safe_to_read_maps()); |
+ return map()->heap(); |
+} |
+ |
+ |
+Isolate* HeapObject::GetIsolate() { |
+ Isolate* i = GetHeap()->isolate(); |
+ ASSERT(i == Isolate::Current()); |
+ return i; |
+} |
+ |
+ |
Map* HeapObject::map() { |
return map_word().ToMap(); |
} |
@@ -1223,25 +1264,25 @@ |
void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) { |
ASSERT(map()->has_fast_elements() == |
- (value->map() == Heap::fixed_array_map() || |
- value->map() == Heap::fixed_cow_array_map())); |
+ (value->map() == GetHeap()->fixed_array_map() || |
+ value->map() == GetHeap()->fixed_cow_array_map())); |
// In the assert below Dictionary is covered under FixedArray. |
ASSERT(value->IsFixedArray() || value->IsExternalArray()); |
WRITE_FIELD(this, kElementsOffset, value); |
- CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode); |
+ CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, mode); |
} |
void JSObject::initialize_properties() { |
- ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array())); |
- WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array()); |
+ ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
+ WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); |
} |
void JSObject::initialize_elements() { |
ASSERT(map()->has_fast_elements()); |
- ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array())); |
- WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array()); |
+ ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
+ WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array()); |
} |
@@ -1260,6 +1301,16 @@ |
ACCESSORS(Oddball, to_number, Object, kToNumberOffset) |
+byte Oddball::kind() { |
+ return READ_BYTE_FIELD(this, kKindOffset); |
+} |
+ |
+ |
+void Oddball::set_kind(byte value) { |
+ WRITE_BYTE_FIELD(this, kKindOffset, value); |
+} |
+ |
+ |
Object* JSGlobalPropertyCell::value() { |
return READ_FIELD(this, kValueOffset); |
} |
@@ -1395,14 +1446,14 @@ |
ASSERT(index < 0); |
int offset = map()->instance_size() + (index * kPointerSize); |
WRITE_FIELD(this, offset, value); |
- CONDITIONAL_WRITE_BARRIER(this, offset, mode); |
+ CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode); |
return value; |
} |
void JSObject::InitializeBody(int object_size, Object* value) { |
- ASSERT(!value->IsHeapObject() || !Heap::InNewSpace(value)); |
+ ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value)); |
for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { |
WRITE_FIELD(this, offset, value); |
} |
@@ -1425,7 +1476,7 @@ |
void Struct::InitializeBody(int object_size) { |
- Object* value = Heap::undefined_value(); |
+ Object* value = GetHeap()->undefined_value(); |
for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { |
WRITE_FIELD(this, offset, value); |
} |
@@ -1471,7 +1522,7 @@ |
void FixedArray::set(int index, Smi* value) { |
- ASSERT(map() != Heap::fixed_cow_array_map()); |
+ ASSERT(map() != HEAP->fixed_cow_array_map()); |
ASSERT(reinterpret_cast<Object*>(value)->IsSmi()); |
int offset = kHeaderSize + index * kPointerSize; |
WRITE_FIELD(this, offset, value); |
@@ -1479,7 +1530,7 @@ |
void FixedArray::set(int index, Object* value) { |
- ASSERT(map() != Heap::fixed_cow_array_map()); |
+ ASSERT(map() != HEAP->fixed_cow_array_map()); |
ASSERT(index >= 0 && index < this->length()); |
int offset = kHeaderSize + index * kPointerSize; |
WRITE_FIELD(this, offset, value); |
@@ -1488,7 +1539,7 @@ |
WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) { |
- if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER; |
+ if (GetHeap()->InNewSpace(this)) return SKIP_WRITE_BARRIER; |
return UPDATE_WRITE_BARRIER; |
} |
@@ -1496,44 +1547,55 @@ |
void FixedArray::set(int index, |
Object* value, |
WriteBarrierMode mode) { |
- ASSERT(map() != Heap::fixed_cow_array_map()); |
+ ASSERT(map() != HEAP->fixed_cow_array_map()); |
ASSERT(index >= 0 && index < this->length()); |
int offset = kHeaderSize + index * kPointerSize; |
WRITE_FIELD(this, offset, value); |
- CONDITIONAL_WRITE_BARRIER(this, offset, mode); |
+ CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode); |
} |
void FixedArray::fast_set(FixedArray* array, int index, Object* value) { |
- ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map()); |
+ ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map()); |
ASSERT(index >= 0 && index < array->length()); |
- ASSERT(!Heap::InNewSpace(value)); |
+ ASSERT(!HEAP->InNewSpace(value)); |
WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value); |
} |
void FixedArray::set_undefined(int index) { |
- ASSERT(map() != Heap::fixed_cow_array_map()); |
+ ASSERT(map() != HEAP->fixed_cow_array_map()); |
+ set_undefined(GetHeap(), index); |
+} |
+ |
+ |
+void FixedArray::set_undefined(Heap* heap, int index) { |
ASSERT(index >= 0 && index < this->length()); |
- ASSERT(!Heap::InNewSpace(Heap::undefined_value())); |
+ ASSERT(!heap->InNewSpace(heap->undefined_value())); |
WRITE_FIELD(this, kHeaderSize + index * kPointerSize, |
- Heap::undefined_value()); |
+ heap->undefined_value()); |
} |
void FixedArray::set_null(int index) { |
- ASSERT(map() != Heap::fixed_cow_array_map()); |
+ set_null(GetHeap(), index); |
+} |
+ |
+ |
+void FixedArray::set_null(Heap* heap, int index) { |
ASSERT(index >= 0 && index < this->length()); |
- ASSERT(!Heap::InNewSpace(Heap::null_value())); |
- WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value()); |
+ ASSERT(!heap->InNewSpace(heap->null_value())); |
+ WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value()); |
} |
void FixedArray::set_the_hole(int index) { |
- ASSERT(map() != Heap::fixed_cow_array_map()); |
+ ASSERT(map() != HEAP->fixed_cow_array_map()); |
ASSERT(index >= 0 && index < this->length()); |
- ASSERT(!Heap::InNewSpace(Heap::the_hole_value())); |
- WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value()); |
+ ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value())); |
+ WRITE_FIELD(this, |
+ kHeaderSize + index * kPointerSize, |
+ GetHeap()->the_hole_value()); |
} |
@@ -1544,19 +1606,20 @@ |
} |
-void FixedArray::set_unchecked(int index, |
+void FixedArray::set_unchecked(Heap* heap, |
+ int index, |
Object* value, |
WriteBarrierMode mode) { |
int offset = kHeaderSize + index * kPointerSize; |
WRITE_FIELD(this, offset, value); |
- CONDITIONAL_WRITE_BARRIER(this, offset, mode); |
+ CONDITIONAL_WRITE_BARRIER(heap, this, offset, mode); |
} |
-void FixedArray::set_null_unchecked(int index) { |
+void FixedArray::set_null_unchecked(Heap* heap, int index) { |
ASSERT(index >= 0 && index < this->length()); |
- ASSERT(!Heap::InNewSpace(Heap::null_value())); |
- WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value()); |
+ ASSERT(!HEAP->InNewSpace(heap->null_value())); |
+ WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value()); |
} |
@@ -1566,9 +1629,9 @@ |
bool DescriptorArray::IsEmpty() { |
- ASSERT(this == Heap::empty_descriptor_array() || |
- this->length() > 2); |
- return this == Heap::empty_descriptor_array(); |
+ ASSERT(this->length() > kFirstIndex || |
+ this == HEAP->empty_descriptor_array()); |
+ return length() <= kFirstIndex; |
} |
@@ -1598,10 +1661,10 @@ |
int DescriptorArray::SearchWithCache(String* name) { |
- int number = DescriptorLookupCache::Lookup(this, name); |
+ int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name); |
if (number == DescriptorLookupCache::kAbsent) { |
number = Search(name); |
- DescriptorLookupCache::Update(this, name, number); |
+ GetIsolate()->descriptor_lookup_cache()->Update(this, name, number); |
} |
return number; |
} |
@@ -1687,8 +1750,8 @@ |
ASSERT(descriptor_number < number_of_descriptors()); |
// Make sure none of the elements in desc are in new space. |
- ASSERT(!Heap::InNewSpace(desc->GetKey())); |
- ASSERT(!Heap::InNewSpace(desc->GetValue())); |
+ ASSERT(!HEAP->InNewSpace(desc->GetKey())); |
+ ASSERT(!HEAP->InNewSpace(desc->GetValue())); |
fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey()); |
FixedArray* content_array = GetContentArray(); |
@@ -1713,6 +1776,30 @@ |
} |
+template<typename Shape, typename Key> |
+int HashTable<Shape, Key>::FindEntry(Key key) { |
+ return FindEntry(GetIsolate(), key); |
+} |
+ |
+ |
+// Find entry for key otherwise return kNotFound. |
+template<typename Shape, typename Key> |
+int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) { |
+ uint32_t capacity = Capacity(); |
+ uint32_t entry = FirstProbe(Shape::Hash(key), capacity); |
+ uint32_t count = 1; |
+ // EnsureCapacity will guarantee the hash table is never full. |
+ while (true) { |
+ Object* element = KeyAt(entry); |
+ if (element == isolate->heap()->undefined_value()) break; // Empty entry. |
+ if (element != isolate->heap()->null_value() && |
+ Shape::IsMatch(key, element)) return entry; |
+ entry = NextProbe(entry, count++, capacity); |
+ } |
+ return kNotFound; |
+} |
+ |
+ |
bool NumberDictionary::requires_slow_elements() { |
Object* max_index_object = get(kMaxNumberKeyIndex); |
if (!max_index_object->IsSmi()) return false; |
@@ -1959,7 +2046,7 @@ |
void ConsString::set_first(String* value, WriteBarrierMode mode) { |
WRITE_FIELD(this, kFirstOffset, value); |
- CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode); |
+ CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, mode); |
} |
@@ -1975,7 +2062,7 @@ |
void ConsString::set_second(String* value, WriteBarrierMode mode) { |
WRITE_FIELD(this, kSecondOffset, value); |
- CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode); |
+ CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, mode); |
} |
@@ -2011,7 +2098,7 @@ |
int cache_size = size(); |
Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex)); |
MemsetPointer(entries_start, |
- Heap::the_hole_value(), |
+ GetHeap()->the_hole_value(), |
cache_size - kEntriesIndex); |
MakeZeroSize(); |
} |
@@ -2728,6 +2815,15 @@ |
} |
+Heap* Map::heap() { |
+ // NOTE: address() helper is not used to save one instruction. |
+ Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_; |
+ ASSERT(heap != NULL); |
+ ASSERT(heap->isolate() == Isolate::Current()); |
+ return heap; |
+} |
+ |
+ |
Object* Code::GetObjectFromEntryAddress(Address location_of_address) { |
return HeapObject:: |
FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize); |
@@ -2742,7 +2838,7 @@ |
void Map::set_prototype(Object* value, WriteBarrierMode mode) { |
ASSERT(value->IsNull() || value->IsJSObject()); |
WRITE_FIELD(this, kPrototypeOffset, value); |
- CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode); |
+ CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, mode); |
} |
@@ -2754,7 +2850,7 @@ |
} |
Map* new_map = Map::cast(obj); |
new_map->set_has_fast_elements(true); |
- Counters::map_slow_to_fast_elements.Increment(); |
+ COUNTERS->map_slow_to_fast_elements()->Increment(); |
return new_map; |
} |
@@ -2767,7 +2863,7 @@ |
} |
Map* new_map = Map::cast(obj); |
new_map->set_has_fast_elements(false); |
- Counters::map_fast_to_slow_elements.Increment(); |
+ COUNTERS->map_fast_to_slow_elements()->Increment(); |
return new_map; |
} |
@@ -2782,7 +2878,7 @@ |
Map* new_map = Map::cast(obj); |
new_map->set_has_fast_elements(false); |
new_map->set_has_external_array_elements(true); |
- Counters::map_to_external_array_elements.Increment(); |
+ COUNTERS->map_to_external_array_elements()->Increment(); |
return new_map; |
} |
@@ -2794,7 +2890,8 @@ |
ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) |
ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset) |
-ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) |
+ACCESSORS_GCSAFE(JSFunction, next_function_link, Object, |
+ kNextFunctionLinkOffset) |
ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) |
ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset) |
@@ -2883,8 +2980,8 @@ |
#endif |
ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset) |
-ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset) |
-ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset) |
+ACCESSORS_GCSAFE(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset) |
+ACCESSORS_GCSAFE(SharedFunctionInfo, initial_map, Object, kInitialMapOffset) |
ACCESSORS(SharedFunctionInfo, instance_class_name, Object, |
kInstanceClassNameOffset) |
ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset) |
@@ -3012,7 +3109,7 @@ |
bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() { |
- return initial_map() != Heap::undefined_value(); |
+ return initial_map() != HEAP->undefined_value(); |
} |
@@ -3091,7 +3188,7 @@ |
void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) { |
WRITE_FIELD(this, kCodeOffset, value); |
- CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode); |
+ ASSERT(!Isolate::Current()->heap()->InNewSpace(value)); |
} |
@@ -3104,7 +3201,7 @@ |
void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value, |
WriteBarrierMode mode) { |
WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value)); |
- CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode); |
+ CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kScopeInfoOffset, mode); |
} |
@@ -3119,7 +3216,8 @@ |
bool SharedFunctionInfo::is_compiled() { |
- return code() != Builtins::builtin(Builtins::LazyCompile); |
+ return code() != |
+ Isolate::Current()->builtins()->builtin(Builtins::LazyCompile); |
} |
@@ -3179,7 +3277,7 @@ |
bool JSFunction::IsMarkedForLazyRecompilation() { |
- return code() == Builtins::builtin(Builtins::LazyRecompile); |
+ return code() == GetIsolate()->builtins()->builtin(Builtins::LazyRecompile); |
} |
@@ -3196,7 +3294,7 @@ |
void JSFunction::set_code(Code* value) { |
// Skip the write barrier because code is never in new space. |
- ASSERT(!Heap::InNewSpace(value)); |
+ ASSERT(!HEAP->InNewSpace(value)); |
Address entry = value->entry(); |
WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry)); |
} |
@@ -3236,7 +3334,7 @@ |
void JSFunction::set_context(Object* value) { |
- ASSERT(value == Heap::undefined_value() || value->IsContext()); |
+ ASSERT(value->IsUndefined() || value->IsContext()); |
WRITE_FIELD(this, kContextOffset, value); |
WRITE_BARRIER(this, kContextOffset); |
} |
@@ -3293,7 +3391,7 @@ |
bool JSFunction::is_compiled() { |
- return code() != Builtins::builtin(Builtins::LazyCompile); |
+ return code() != GetIsolate()->builtins()->builtin(Builtins::LazyCompile); |
} |
@@ -3326,7 +3424,7 @@ |
Code* value) { |
ASSERT(id < kJSBuiltinsCount); // id is unsigned. |
WRITE_FIELD(this, OffsetOfCodeWithId(id), value); |
- ASSERT(!Heap::InNewSpace(value)); |
+ ASSERT(!HEAP->InNewSpace(value)); |
} |
@@ -3476,8 +3574,8 @@ |
JSObject::ElementsKind JSObject::GetElementsKind() { |
if (map()->has_fast_elements()) { |
- ASSERT(elements()->map() == Heap::fixed_array_map() || |
- elements()->map() == Heap::fixed_cow_array_map()); |
+ ASSERT(elements()->map() == GetHeap()->fixed_array_map() || |
+ elements()->map() == GetHeap()->fixed_cow_array_map()); |
return FAST_ELEMENTS; |
} |
HeapObject* array = elements(); |
@@ -3487,6 +3585,7 @@ |
ASSERT(array->IsDictionary()); |
return DICTIONARY_ELEMENTS; |
} |
+ ASSERT(!map()->has_fast_elements()); |
if (array->IsExternalArray()) { |
switch (array->map()->instance_type()) { |
case EXTERNAL_BYTE_ARRAY_TYPE: |
@@ -3572,16 +3671,17 @@ |
MaybeObject* JSObject::EnsureWritableFastElements() { |
ASSERT(HasFastElements()); |
FixedArray* elems = FixedArray::cast(elements()); |
- if (elems->map() != Heap::fixed_cow_array_map()) return elems; |
+ Isolate* isolate = GetIsolate(); |
+ if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; |
Object* writable_elems; |
- { MaybeObject* maybe_writable_elems = |
- Heap::CopyFixedArrayWithMap(elems, Heap::fixed_array_map()); |
+ { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap( |
+ elems, isolate->heap()->fixed_array_map()); |
if (!maybe_writable_elems->ToObject(&writable_elems)) { |
return maybe_writable_elems; |
} |
} |
set_elements(FixedArray::cast(writable_elems)); |
- Counters::cow_arrays_converted.Increment(); |
+ isolate->counters()->cow_arrays_converted()->Increment(); |
return writable_elems; |
} |
@@ -3721,7 +3821,7 @@ |
Object* JSObject::BypassGlobalProxy() { |
if (IsJSGlobalProxy()) { |
Object* proto = GetPrototype(); |
- if (proto->IsNull()) return Heap::undefined_value(); |
+ if (proto->IsNull()) return GetHeap()->undefined_value(); |
ASSERT(proto->IsJSGlobalObject()); |
return proto; |
} |
@@ -3732,7 +3832,7 @@ |
bool JSObject::HasHiddenPropertiesObject() { |
ASSERT(!IsJSGlobalProxy()); |
return GetPropertyAttributePostInterceptor(this, |
- Heap::hidden_symbol(), |
+ GetHeap()->hidden_symbol(), |
false) != ABSENT; |
} |
@@ -3745,7 +3845,7 @@ |
// object. |
Object* result = |
GetLocalPropertyPostInterceptor(this, |
- Heap::hidden_symbol(), |
+ GetHeap()->hidden_symbol(), |
&attributes)->ToObjectUnchecked(); |
return result; |
} |
@@ -3753,7 +3853,7 @@ |
MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) { |
ASSERT(!IsJSGlobalProxy()); |
- return SetPropertyPostInterceptor(Heap::hidden_symbol(), |
+ return SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), |
hidden_obj, |
DONT_ENUM, |
kNonStrictMode); |
@@ -3821,12 +3921,57 @@ |
} |
-void Map::ClearCodeCache() { |
+bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) { |
+ ASSERT(other->IsNumber()); |
+ return key == static_cast<uint32_t>(other->Number()); |
+} |
+ |
+ |
+uint32_t NumberDictionaryShape::Hash(uint32_t key) { |
+ return ComputeIntegerHash(key); |
+} |
+ |
+ |
+uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) { |
+ ASSERT(other->IsNumber()); |
+ return ComputeIntegerHash(static_cast<uint32_t>(other->Number())); |
+} |
+ |
+ |
+MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) { |
+ return Isolate::Current()->heap()->NumberFromUint32(key); |
+} |
+ |
+ |
+bool StringDictionaryShape::IsMatch(String* key, Object* other) { |
+ // We know that all entries in a hash table had their hash keys created. |
+ // Use that knowledge to have fast failure. |
+ if (key->Hash() != String::cast(other)->Hash()) return false; |
+ return key->Equals(String::cast(other)); |
+} |
+ |
+ |
+uint32_t StringDictionaryShape::Hash(String* key) { |
+ return key->Hash(); |
+} |
+ |
+ |
+uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) { |
+ return String::cast(other)->Hash(); |
+} |
+ |
+ |
+MaybeObject* StringDictionaryShape::AsObject(String* key) { |
+ return key; |
+} |
+ |
+ |
+void Map::ClearCodeCache(Heap* heap) { |
// No write barrier is needed since empty_fixed_array is not in new space. |
// Please note this function is used during marking: |
// - MarkCompactCollector::MarkUnmarkedObject |
- ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array())); |
- WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array()); |
+ ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array())); |
+ WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array()); |
} |
@@ -3839,7 +3984,7 @@ |
// constantly growing. |
Expand(required_size + (required_size >> 3)); |
// It's a performance benefit to keep a frequently used array in new-space. |
- } else if (!Heap::new_space()->Contains(elts) && |
+ } else if (!GetHeap()->new_space()->Contains(elts) && |
required_size < kArraySizeThatFitsComfortablyInNewSpace) { |
// Expand will allocate a new backing store in new space even if the size |
// we asked for isn't larger than what we had before. |
@@ -3861,10 +4006,25 @@ |
MaybeObject* FixedArray::Copy() { |
if (length() == 0) return this; |
- return Heap::CopyFixedArray(this); |
+ return GetHeap()->CopyFixedArray(this); |
} |
+Relocatable::Relocatable(Isolate* isolate) { |
+ ASSERT(isolate == Isolate::Current()); |
+ isolate_ = isolate; |
+ prev_ = isolate->relocatable_top(); |
+ isolate->set_relocatable_top(this); |
+} |
+ |
+ |
+Relocatable::~Relocatable() { |
+ ASSERT(isolate_ == Isolate::Current()); |
+ ASSERT_EQ(isolate_->relocatable_top(), this); |
+ isolate_->set_relocatable_top(prev_); |
+} |
+ |
+ |
int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) { |
return map->instance_size(); |
} |