From 3e59faef0cfe7a85bbec2c50e5b92ba1dad70528 Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Thu, 31 Mar 2011 10:55:53 +0000 Subject: [PATCH] Microoptimizations to the way we get the current heap. Review URL: http://codereview.chromium.org/6759030 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7455 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/objects-inl.h | 37 ++++- src/objects.cc | 389 +++++++++++++++++++++++++--------------------- src/objects.h | 8 + 3 files changed, 250 insertions(+), 184 deletions(-) diff --git a/src/objects-inl.h b/src/objects-inl.h index 5395bbbf2..39c134a3a 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1158,12 +1158,9 @@ void HeapObject::VerifySmiField(int offset) { 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(); + uintptr_t addr = reinterpret_cast(this); + addr >>= kHeapDescriptorGranularityBits; + return heap_descriptors[addr].heap; } @@ -2862,6 +2859,34 @@ Heap* Map::heap() { } +Heap* Code::heap() { + // NOTE: address() helper is not used to save one instruction. + Heap* heap = Page::FromAddress(reinterpret_cast
(this))->heap_; + ASSERT(heap != NULL); + ASSERT(heap->isolate() == Isolate::Current()); + return heap; +} + + +Isolate* Code::isolate() { + return heap()->isolate(); +} + + +Heap* JSGlobalPropertyCell::heap() { + // NOTE: address() helper is not used to save one instruction. + Heap* heap = Page::FromAddress(reinterpret_cast
(this))->heap_; + ASSERT(heap != NULL); + ASSERT(heap->isolate() == Isolate::Current()); + return heap; +} + + +Isolate* JSGlobalPropertyCell::isolate() { + return heap()->isolate(); +} + + Object* Code::GetObjectFromEntryAddress(Address location_of_address) { return HeapObject:: FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize); diff --git a/src/objects.cc b/src/objects.cc index 8cb36e91f..9a5357a33 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -113,39 +113,47 @@ Object* Object::ToBoolean() { if (IsSmi()) { return Isolate::Current()->heap()->ToBoolean(Smi::cast(this)->value() != 0); } - if (IsUndefined() || IsNull()) { - return HeapObject::cast(this)->GetHeap()->false_value(); + HeapObject* heap_object = HeapObject::cast(this); + if (heap_object->IsUndefined() || heap_object->IsNull()) { + return heap_object->GetHeap()->false_value(); } // Undetectable object is false - if (IsUndetectableObject()) { - return HeapObject::cast(this)->GetHeap()->false_value(); + if (heap_object->IsUndetectableObject()) { + return heap_object->GetHeap()->false_value(); } - if (IsString()) { - return HeapObject::cast(this)->GetHeap()->ToBoolean( + if (heap_object->IsString()) { + return heap_object->GetHeap()->ToBoolean( String::cast(this)->length() != 0); } - if (IsHeapNumber()) { + if (heap_object->IsHeapNumber()) { return HeapNumber::cast(this)->HeapNumberToBoolean(); } - return Isolate::Current()->heap()->true_value(); + return heap_object->GetHeap()->true_value(); } void Object::Lookup(String* name, LookupResult* result) { - if (IsJSObject()) return JSObject::cast(this)->Lookup(name, result); Object* holder = NULL; - if (IsString()) { - Heap* heap = HeapObject::cast(this)->GetHeap(); - Context* global_context = heap->isolate()->context()->global_context(); - holder = global_context->string_function()->instance_prototype(); - } else if (IsNumber()) { + if (IsSmi()) { Heap* heap = Isolate::Current()->heap(); Context* global_context = heap->isolate()->context()->global_context(); holder = global_context->number_function()->instance_prototype(); - } else if (IsBoolean()) { - Heap* heap = HeapObject::cast(this)->GetHeap(); - Context* global_context = heap->isolate()->context()->global_context(); - holder = global_context->boolean_function()->instance_prototype(); + } else { + HeapObject* heap_object = HeapObject::cast(this); + if (heap_object->IsJSObject()) { + return JSObject::cast(this)->Lookup(name, result); + } + Heap* heap = heap_object->GetHeap(); + if (heap_object->IsString()) { + Context* global_context = heap->isolate()->context()->global_context(); + holder = global_context->string_function()->instance_prototype(); + } else if (heap_object->IsHeapNumber()) { + Context* global_context = heap->isolate()->context()->global_context(); + holder = global_context->number_function()->instance_prototype(); + } else if (heap_object->IsBoolean()) { + Context* global_context = heap->isolate()->context()->global_context(); + holder = global_context->boolean_function()->instance_prototype(); + } } ASSERT(holder != NULL); // Cannot handle null or undefined. JSObject::cast(holder)->Lookup(name, result); @@ -247,7 +255,6 @@ MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( LookupResult* result, String* name, PropertyAttributes* attributes) { - Heap* heap = name->GetHeap(); if (result->IsProperty()) { switch (result->type()) { case CALLBACKS: { @@ -299,6 +306,7 @@ MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( // No accessible property found. *attributes = ABSENT; + Heap* heap = name->GetHeap(); heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); return heap->undefined_value(); } @@ -309,7 +317,6 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( LookupResult* result, String* name, bool continue_search) { - Heap* heap = name->GetHeap(); if (result->IsProperty()) { switch (result->type()) { case CALLBACKS: { @@ -363,7 +370,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( } } - heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); + GetHeap()->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); return ABSENT; } @@ -397,11 +404,11 @@ MaybeObject* JSObject::SetNormalizedProperty(String* name, Object* value, PropertyDetails details) { ASSERT(!HasFastProperties()); - Heap* heap = name->GetHeap(); int entry = property_dictionary()->FindEntry(name); if (entry == StringDictionary::kNotFound) { Object* store_value = value; if (IsGlobalObject()) { + Heap* heap = name->GetHeap(); MaybeObject* maybe_store_value = heap->AllocateJSGlobalPropertyCell(value); if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; @@ -433,7 +440,6 @@ MaybeObject* JSObject::SetNormalizedProperty(String* name, MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { ASSERT(!HasFastProperties()); - Heap* heap = GetHeap(); StringDictionary* dictionary = property_dictionary(); int entry = dictionary->FindEntry(name); if (entry != StringDictionary::kNotFound) { @@ -441,7 +447,7 @@ MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { if (IsGlobalObject()) { PropertyDetails details = dictionary->DetailsAt(entry); if (details.IsDontDelete()) { - if (mode != FORCE_DELETION) return heap->false_value(); + if (mode != FORCE_DELETION) return GetHeap()->false_value(); // When forced to delete global properties, we have to make a // map change to invalidate any ICs that think they can load // from the DontDelete cell without checking if it contains @@ -454,13 +460,13 @@ MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { } JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); - cell->set_value(heap->the_hole_value()); + cell->set_value(cell->heap()->the_hole_value()); dictionary->DetailsAtPut(entry, details.AsDeleted()); } else { return dictionary->DeleteProperty(entry, mode); } } - return heap->true_value(); + return GetHeap()->true_value(); } @@ -550,22 +556,31 @@ MaybeObject* Object::GetProperty(Object* receiver, MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { - if (IsJSObject()) { - return JSObject::cast(this)->GetElementWithReceiver(receiver, index); - } - Object* holder = NULL; - Context* global_context = Isolate::Current()->context()->global_context(); - if (IsString()) { - holder = global_context->string_function()->instance_prototype(); - } else if (IsNumber()) { + if (IsSmi()) { + Context* global_context = Isolate::Current()->context()->global_context(); holder = global_context->number_function()->instance_prototype(); - } else if (IsBoolean()) { - holder = global_context->boolean_function()->instance_prototype(); } else { - // Undefined and null have no indexed properties. - ASSERT(IsUndefined() || IsNull()); - return HEAP->undefined_value(); + HeapObject* heap_object = HeapObject::cast(this); + + if (heap_object->IsJSObject()) { + return JSObject::cast(this)->GetElementWithReceiver(receiver, index); + } + Heap* heap = heap_object->GetHeap(); + Isolate* isolate = heap->isolate(); + + Context* global_context = isolate->context()->global_context(); + if (heap_object->IsString()) { + holder = global_context->string_function()->instance_prototype(); + } else if (heap_object->IsHeapNumber()) { + holder = global_context->number_function()->instance_prototype(); + } else if (heap_object->IsBoolean()) { + holder = global_context->boolean_function()->instance_prototype(); + } else { + // Undefined and null have no indexed properties. + ASSERT(heap_object->IsUndefined() || heap_object->IsNull()); + return heap->undefined_value(); + } } return JSObject::cast(holder)->GetElementWithReceiver(receiver, index); @@ -573,14 +588,28 @@ MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { Object* Object::GetPrototype() { + if (IsSmi()) { + Heap* heap = Isolate::Current()->heap(); + Context* context = heap->isolate()->context()->global_context(); + return context->number_function()->instance_prototype(); + } + + HeapObject* heap_object = HeapObject::cast(this); + // The object is either a number, a string, a boolean, or a real JS object. - if (IsJSObject()) return JSObject::cast(this)->map()->prototype(); - Heap* heap = Isolate::Current()->heap(); + if (heap_object->IsJSObject()) { + return JSObject::cast(this)->map()->prototype(); + } + Heap* heap = heap_object->GetHeap(); Context* context = heap->isolate()->context()->global_context(); - if (IsNumber()) return context->number_function()->instance_prototype(); - if (IsString()) return context->string_function()->instance_prototype(); - if (IsBoolean()) { + if (heap_object->IsHeapNumber()) { + return context->number_function()->instance_prototype(); + } + if (heap_object->IsString()) { + return context->string_function()->instance_prototype(); + } + if (heap_object->IsBoolean()) { return context->boolean_function()->instance_prototype(); } else { return heap->null_value(); @@ -908,8 +937,9 @@ void JSObject::JSObjectShortPrint(StringStream* accumulator) { // All other JSObjects are rather similar to each other (JSObject, // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue). default: { - Heap* heap = GetHeap(); - Object* constructor = map()->constructor(); + Map* map_of_this = map(); + Heap* heap = map_of_this->heap(); + Object* constructor = map_of_this->constructor(); bool printed = false; if (constructor->IsHeapObject() && !heap->Contains(HeapObject::cast(constructor))) { @@ -1350,8 +1380,7 @@ MaybeObject* JSObject::AddConstantFunctionProperty( String* name, JSFunction* function, PropertyAttributes attributes) { - Heap* heap = GetHeap(); - ASSERT(!heap->InNewSpace(function)); + ASSERT(!GetHeap()->InNewSpace(function)); // Allocate new instance descriptors with (name, function) added ConstantFunctionDescriptor d(name, function, attributes); @@ -1376,6 +1405,7 @@ MaybeObject* JSObject::AddConstantFunctionProperty( // If the old map is the global object map (from new Object()), // then transitions are not added to it, so we are done. + Heap* heap = old_map->heap(); if (old_map == heap->isolate()->context()->global_context()-> object_function()->map()) { return function; @@ -1412,7 +1442,6 @@ MaybeObject* JSObject::AddSlowProperty(String* name, Object* value, PropertyAttributes attributes) { ASSERT(!HasFastProperties()); - Heap* heap = GetHeap(); StringDictionary* dict = property_dictionary(); Object* store_value = value; if (IsGlobalObject()) { @@ -1429,6 +1458,7 @@ MaybeObject* JSObject::AddSlowProperty(String* name, dict->SetEntry(entry, name, store_value, details); return value; } + Heap* heap = GetHeap(); { MaybeObject* maybe_store_value = heap->AllocateJSGlobalPropertyCell(value); if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; @@ -1450,8 +1480,9 @@ MaybeObject* JSObject::AddProperty(String* name, PropertyAttributes attributes, StrictModeFlag strict_mode) { ASSERT(!IsJSGlobalProxy()); - Heap* heap = GetHeap(); - if (!map()->is_extensible()) { + Map* map_of_this = map(); + Heap* heap = map_of_this->heap(); + if (!map_of_this->is_extensible()) { if (strict_mode == kNonStrictMode) { return heap->undefined_value(); } else { @@ -1463,7 +1494,7 @@ MaybeObject* JSObject::AddProperty(String* name, } if (HasFastProperties()) { // Ensure the descriptor array does not get too big. - if (map()->instance_descriptors()->number_of_descriptors() < + if (map_of_this->instance_descriptors()->number_of_descriptors() < DescriptorArray::kMaxNumberOfDescriptors) { if (value->IsJSFunction() && !heap->InNewSpace(value)) { return AddConstantFunctionProperty(name, @@ -1537,7 +1568,7 @@ MaybeObject* JSObject::ConvertDescriptorToFieldAndMapTransition( return result; } // Do not add transitions to the map of "new Object()". - if (map() == GetHeap()->isolate()->context()->global_context()-> + if (map() == old_map->heap()->isolate()->context()->global_context()-> object_function()->map()) { return result; } @@ -1836,8 +1867,9 @@ void Map::LookupInDescriptors(JSObject* holder, MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type, bool safe_to_add_transition) { + Heap* current_heap = heap(); DescriptorArray* descriptors = instance_descriptors(); - String* external_array_sentinel_name = GetIsolate()->heap()->empty_symbol(); + String* external_array_sentinel_name = current_heap->empty_symbol(); if (safe_to_add_transition) { // It's only safe to manipulate the descriptor array if it would be @@ -1845,7 +1877,8 @@ MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type, ASSERT(!is_shared()); // no transitions can be added to shared maps. // Check if the external array transition already exists. - DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache(); + DescriptorLookupCache* cache = + current_heap->isolate()->descriptor_lookup_cache(); int index = cache->Lookup(descriptors, external_array_sentinel_name); if (index == DescriptorLookupCache::kAbsent) { index = descriptors->Search(external_array_sentinel_name); @@ -1979,7 +2012,6 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, String* name, Object* value, bool check_prototype) { - Heap* heap = GetHeap(); if (check_prototype && !result->IsProperty()) { LookupCallbackSetterInPrototypes(name, result); } @@ -2020,6 +2052,7 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, HandleScope scope; Handle value_handle(value); + Heap* heap = GetHeap(); heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); return *value_handle; } @@ -2157,7 +2190,6 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( String* name, Object* value, PropertyAttributes attributes) { - Heap* heap = GetHeap(); // Make sure that the top context does not change when doing callbacks or // interceptor calls. @@ -2165,9 +2197,11 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( LookupResult result; LocalLookup(name, &result); // Check access rights if needed. - if (IsAccessCheckNeeded() - && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { - return SetPropertyWithFailedAccessCheck(&result, name, value, false); + if (IsAccessCheckNeeded()) { + Heap* heap = GetHeap(); + if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { + return SetPropertyWithFailedAccessCheck(&result, name, value, false); + } } if (IsJSGlobalProxy()) { @@ -2318,14 +2352,15 @@ PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver, LookupResult* result, String* name, bool continue_search) { - Heap* heap = GetHeap(); // Check access rights if needed. - if (IsAccessCheckNeeded() && - !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) { - return GetPropertyAttributeWithFailedAccessCheck(receiver, - result, - name, - continue_search); + if (IsAccessCheckNeeded()) { + Heap* heap = GetHeap(); + if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) { + return GetPropertyAttributeWithFailedAccessCheck(receiver, + result, + name, + continue_search); + } } if (result->IsProperty()) { switch (result->type()) { @@ -2465,10 +2500,10 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, // JSGlobalProxy must never be normalized ASSERT(!IsJSGlobalProxy()); - Heap* heap = GetHeap(); + Map* map_of_this = map(); // Allocate new content. - int property_count = map()->NumberOfDescribedProperties(); + int property_count = map_of_this->NumberOfDescribedProperties(); if (expected_additional_properties > 0) { property_count += expected_additional_properties; } else { @@ -2481,7 +2516,7 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, } StringDictionary* dictionary = StringDictionary::cast(obj); - DescriptorArray* descs = map()->instance_descriptors(); + DescriptorArray* descs = map_of_this->instance_descriptors(); for (int i = 0; i < descs->number_of_descriptors(); i++) { PropertyDetails details = descs->GetDetails(i); switch (details.type()) { @@ -2531,11 +2566,14 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, } } + Heap* current_heap = map_of_this->heap(); + // Copy the next enumeration index from instance descriptor. - int index = map()->instance_descriptors()->NextEnumerationIndex(); + int index = map_of_this->instance_descriptors()->NextEnumerationIndex(); dictionary->SetNextEnumerationIndex(index); - { MaybeObject* maybe_obj = heap->isolate()->context()->global_context()-> + { MaybeObject* maybe_obj = + current_heap->isolate()->context()->global_context()-> normalized_map_cache()->Get(this, mode); if (!maybe_obj->ToObject(&obj)) return maybe_obj; } @@ -2546,17 +2584,17 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, // Resize the object in the heap if necessary. int new_instance_size = new_map->instance_size(); - int instance_size_delta = map()->instance_size() - new_instance_size; + int instance_size_delta = map_of_this->instance_size() - new_instance_size; ASSERT(instance_size_delta >= 0); - heap->CreateFillerObjectAt(this->address() + new_instance_size, - instance_size_delta); + current_heap->CreateFillerObjectAt(this->address() + new_instance_size, + instance_size_delta); set_map(new_map); - map()->set_instance_descriptors(heap->empty_descriptor_array()); + new_map->set_instance_descriptors(current_heap->empty_descriptor_array()); set_properties(dictionary); - heap->isolate()->counters()->props_to_dictionary()->Increment(); + current_heap->isolate()->counters()->props_to_dictionary()->Increment(); #ifdef DEBUG if (FLAG_trace_normalization) { @@ -2579,10 +2617,11 @@ MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { MaybeObject* JSObject::NormalizeElements() { ASSERT(!HasExternalArrayElements()); if (HasDictionaryElements()) return this; - ASSERT(map()->has_fast_elements()); + Map* old_map = map(); + ASSERT(old_map->has_fast_elements()); Object* obj; - { MaybeObject* maybe_obj = map()->GetSlowElementsMap(); + { MaybeObject* maybe_obj = old_map->GetSlowElementsMap(); if (!maybe_obj->ToObject(&obj)) return maybe_obj; } Map* new_map = Map::cast(obj); @@ -2617,7 +2656,7 @@ MaybeObject* JSObject::NormalizeElements() { set_map(new_map); set_elements(dictionary); - new_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> + new_map->heap()->isolate()->counters()->elements_to_dictionary()-> Increment(); #ifdef DEBUG @@ -2634,10 +2673,9 @@ MaybeObject* JSObject::NormalizeElements() { MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, DeleteMode mode) { // Check local property, ignore interceptor. - Heap* heap = GetHeap(); LookupResult result; LocalLookupRealNamedProperty(name, &result); - if (!result.IsProperty()) return heap->true_value(); + if (!result.IsProperty()) return GetHeap()->true_value(); // Normalize object if needed. Object* obj; @@ -2683,7 +2721,6 @@ MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) { MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index, DeleteMode mode) { - Heap* heap = GetHeap(); ASSERT(!HasExternalArrayElements()); switch (GetElementsKind()) { case FAST_ELEMENTS: { @@ -2711,7 +2748,7 @@ MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index, UNREACHABLE(); break; } - return heap->true_value(); + return GetHeap()->true_value(); } @@ -2884,16 +2921,17 @@ MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { // Check whether this object references another object. bool JSObject::ReferencesObject(Object* obj) { - Heap* heap = GetHeap(); + Map* map_of_this = map(); + Heap* heap = map_of_this->heap(); AssertNoAllocation no_alloc; // Is the object the constructor for this object? - if (map()->constructor() == obj) { + if (map_of_this->constructor() == obj) { return true; } // Is the object the prototype for this object? - if (map()->prototype() == obj) { + if (map_of_this->prototype() == obj) { return true; } @@ -3503,7 +3541,6 @@ Object* JSObject::LookupAccessor(String* name, bool is_getter) { Object* JSObject::SlowReverseLookup(Object* value) { - Heap* heap = GetHeap(); if (HasFastProperties()) { DescriptorArray* descs = map()->instance_descriptors(); for (int i = 0; i < descs->number_of_descriptors(); i++) { @@ -3517,7 +3554,7 @@ Object* JSObject::SlowReverseLookup(Object* value) { } } } - return heap->undefined_value(); + return GetHeap()->undefined_value(); } else { return property_dictionary()->SlowReverseLookup(value); } @@ -3621,7 +3658,7 @@ MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { // Allocate the code cache if not present. if (code_cache()->IsFixedArray()) { Object* result; - { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache(); + { MaybeObject* maybe_result = code->heap()->AllocateCodeCache(); if (!maybe_result->ToObject(&result)) return maybe_result; } set_code_cache(result); @@ -3807,7 +3844,6 @@ Object* CodeCache::Lookup(String* name, Code::Flags flags) { Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) { - Heap* heap = GetHeap(); FixedArray* cache = default_cache(); int length = cache->length(); for (int i = 0; i < length; i += kCodeCacheEntrySize) { @@ -3822,7 +3858,7 @@ Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) { } } } - return heap->undefined_value(); + return GetHeap()->undefined_value(); } @@ -3913,7 +3949,7 @@ class CodeCacheHashTableKey : public HashTableKey { MUST_USE_RESULT MaybeObject* AsObject() { ASSERT(code_ != NULL); Object* obj; - { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2); + { MaybeObject* maybe_obj = code_->heap()->AllocateFixedArray(2); if (!maybe_obj->ToObject(&obj)) return maybe_obj; } FixedArray* pair = FixedArray::cast(obj); @@ -3991,7 +4027,6 @@ static bool HasKey(FixedArray* array, Object* key) { MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { - Heap* heap = GetHeap(); ASSERT(!array->HasExternalArrayElements()); switch (array->GetElementsKind()) { case JSObject::FAST_ELEMENTS: @@ -4002,7 +4037,7 @@ MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { // Allocate a temporary fixed array. Object* object; - { MaybeObject* maybe_object = heap->AllocateFixedArray(size); + { MaybeObject* maybe_object = GetHeap()->AllocateFixedArray(size); if (!maybe_object->ToObject(&object)) return maybe_object; } FixedArray* key_array = FixedArray::cast(object); @@ -4022,12 +4057,11 @@ MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { UNREACHABLE(); } UNREACHABLE(); - return heap->null_value(); // Failure case needs to "return" a value. + return GetHeap()->null_value(); // Failure case needs to "return" a value. } MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { - Heap* heap = GetHeap(); int len0 = length(); #ifdef DEBUG if (FLAG_enable_slow_asserts) { @@ -4053,7 +4087,7 @@ MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { // Allocate the result Object* obj; - { MaybeObject* maybe_obj = heap->AllocateFixedArray(len0 + extra); + { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(len0 + extra); if (!maybe_obj->ToObject(&obj)) return maybe_obj; } // Fill in the content @@ -5373,7 +5407,7 @@ bool String::MarkAsUndetectable() { if (StringShape(this).IsSymbol()) return false; Map* map = this->map(); - Heap* heap = map->GetHeap(); + Heap* heap = map->heap(); if (map == heap->string_map()) { this->set_map(heap->undetectable_string_map()); return true; @@ -5702,17 +5736,18 @@ MaybeObject* JSFunction::SetPrototype(Object* value) { // used for constructing objects to the original object prototype. // See ECMA-262 13.2.2. if (!value->IsJSObject()) { - Heap* heap = GetHeap(); // Copy the map so this does not affect unrelated functions. // Remove map transitions because they point to maps with a // different prototype. - Object* new_map; + Object* new_object; { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); - if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + if (!maybe_new_map->ToObject(&new_object)) return maybe_new_map; } - set_map(Map::cast(new_map)); - map()->set_constructor(value); - map()->set_non_instance_prototype(true); + Map* new_map = Map::cast(new_object); + Heap* heap = new_map->heap(); + set_map(new_map); + new_map->set_constructor(value); + new_map->set_non_instance_prototype(true); construct_prototype = heap->isolate()->context()->global_context()-> initial_object_prototype(); @@ -5740,7 +5775,7 @@ Object* JSFunction::RemovePrototype() { ASSERT(shared()->strict_mode() || map() == global_context->function_map()); set_map(no_prototype_map); - set_prototype_or_initial_map(GetHeap()->the_hole_value()); + set_prototype_or_initial_map(no_prototype_map->heap()->the_hole_value()); return this; } @@ -5822,8 +5857,6 @@ int SharedFunctionInfo::CalculateInObjectProperties() { bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) { - Heap* heap = GetHeap(); - // Check the basic conditions for generating inline constructor code. if (!FLAG_inline_new || !has_only_simple_this_property_assignments() @@ -5837,6 +5870,8 @@ bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) { return true; } + Heap* heap = GetHeap(); + // Traverse the proposed prototype chain looking for setters for properties of // the same names as are set by the inline constructor. for (Object* obj = prototype; @@ -6156,7 +6191,7 @@ void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) { void Code::InvalidateRelocation() { - set_relocation_info(GetHeap()->empty_byte_array()); + set_relocation_info(heap()->empty_byte_array()); } @@ -6734,7 +6769,6 @@ static Failure* ArrayLengthRangeError(Heap* heap) { MaybeObject* JSObject::SetElementsLength(Object* len) { - Heap* heap = GetHeap(); // We should never end in here with a pixel or external array. ASSERT(AllowsSetElementsLength()); @@ -6742,7 +6776,7 @@ MaybeObject* JSObject::SetElementsLength(Object* len) { Object* smi_length = Smi::FromInt(0); if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { const int value = Smi::cast(smi_length)->value(); - if (value < 0) return ArrayLengthRangeError(heap); + if (value < 0) return ArrayLengthRangeError(GetHeap()); switch (GetElementsKind()) { case FAST_ELEMENTS: { int old_capacity = FixedArray::cast(elements())->length(); @@ -6808,14 +6842,14 @@ MaybeObject* JSObject::SetElementsLength(Object* len) { if (len->ToArrayIndex(&length)) { return SetSlowElements(len); } else { - return ArrayLengthRangeError(heap); + return ArrayLengthRangeError(GetHeap()); } } // len is not a number so make the array size one and // set only element to len. Object* obj; - { MaybeObject* maybe_obj = heap->AllocateFixedArray(1); + { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1); if (!maybe_obj->ToObject(&obj)) return maybe_obj; } FixedArray::cast(obj)->set(0, len); @@ -6970,13 +7004,13 @@ bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) { JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { - Heap* heap = GetHeap(); - // Check access rights if needed. - if (IsAccessCheckNeeded() && - !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { - heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); - return UNDEFINED_ELEMENT; + if (IsAccessCheckNeeded()) { + Heap* heap = GetHeap(); + if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { + heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); + return UNDEFINED_ELEMENT; + } } if (IsJSGlobalProxy()) { @@ -7042,13 +7076,13 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { - Heap* heap = GetHeap(); - // Check access rights if needed. - if (IsAccessCheckNeeded() && - !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { - heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); - return false; + if (IsAccessCheckNeeded()) { + Heap* heap = GetHeap(); + if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { + heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); + return false; + } } // Check for lookup interceptor @@ -7320,14 +7354,15 @@ MaybeObject* JSObject::SetElement(uint32_t index, Object* value, StrictModeFlag strict_mode, bool check_prototype) { - Heap* heap = GetHeap(); // Check access rights if needed. - if (IsAccessCheckNeeded() && - !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { - HandleScope scope; - Handle value_handle(value); - heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); - return *value_handle; + if (IsAccessCheckNeeded()) { + Heap* heap = GetHeap(); + if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { + HandleScope scope; + Handle value_handle(value); + heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); + return *value_handle; + } } if (IsJSGlobalProxy()) { @@ -7522,7 +7557,6 @@ MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver, uint32_t index) { - Heap* heap = GetHeap(); // Get element works for both JSObject and JSArray since // JSArray::length cannot change. switch (GetElementsKind()) { @@ -7571,7 +7605,7 @@ MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver, // Continue searching via the prototype chain. Object* pt = GetPrototype(); - if (pt->IsNull()) return heap->undefined_value(); + if (pt->IsNull()) return GetHeap()->undefined_value(); return pt->GetElementWithReceiver(receiver, index); } @@ -7613,12 +7647,13 @@ MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver, MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, uint32_t index) { - Heap* heap = GetHeap(); // Check access rights if needed. - if (IsAccessCheckNeeded() && - !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) { - heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); - return heap->undefined_value(); + if (IsAccessCheckNeeded()) { + Heap* heap = GetHeap(); + if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) { + heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); + return heap->undefined_value(); + } } if (HasIndexedInterceptor()) { @@ -7669,6 +7704,7 @@ MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, } Object* pt = GetPrototype(); + Heap* heap = GetHeap(); if (pt == heap->null_value()) return heap->undefined_value(); return pt->GetElementWithReceiver(receiver, index); } @@ -7895,7 +7931,6 @@ MaybeObject* JSObject::GetPropertyPostInterceptor( JSObject* receiver, String* name, PropertyAttributes* attributes) { - Heap* heap = GetHeap(); // Check local property in holder, ignore interceptor. LookupResult result; LocalLookupRealNamedProperty(name, &result); @@ -7905,7 +7940,7 @@ MaybeObject* JSObject::GetPropertyPostInterceptor( // Continue searching via the prototype chain. Object* pt = GetPrototype(); *attributes = ABSENT; - if (pt->IsNull()) return heap->undefined_value(); + if (pt->IsNull()) return GetHeap()->undefined_value(); return pt->GetPropertyWithReceiver(receiver, name, attributes); } @@ -7914,14 +7949,13 @@ MaybeObject* JSObject::GetLocalPropertyPostInterceptor( JSObject* receiver, String* name, PropertyAttributes* attributes) { - Heap* heap = GetHeap(); // Check local property in holder, ignore interceptor. LookupResult result; LocalLookupRealNamedProperty(name, &result); if (result.IsProperty()) { return GetProperty(receiver, &result, name, attributes); } - return heap->undefined_value(); + return GetHeap()->undefined_value(); } @@ -7966,12 +8000,13 @@ MaybeObject* JSObject::GetPropertyWithInterceptor( bool JSObject::HasRealNamedProperty(String* key) { - Heap* heap = GetHeap(); // Check access rights if needed. - if (IsAccessCheckNeeded() && - !heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) { - heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); - return false; + if (IsAccessCheckNeeded()) { + Heap* heap = GetHeap(); + if (!heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) { + heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); + return false; + } } LookupResult result; @@ -7981,12 +8016,13 @@ bool JSObject::HasRealNamedProperty(String* key) { bool JSObject::HasRealElementProperty(uint32_t index) { - Heap* heap = GetHeap(); // Check access rights if needed. - if (IsAccessCheckNeeded() && - !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { - heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); - return false; + if (IsAccessCheckNeeded()) { + Heap* heap = GetHeap(); + if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { + heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); + return false; + } } // Handle [] on String objects. @@ -8025,17 +8061,18 @@ bool JSObject::HasRealElementProperty(uint32_t index) { } // All possibilities have been handled above already. UNREACHABLE(); - return heap->null_value(); + return GetHeap()->null_value(); } bool JSObject::HasRealNamedCallbackProperty(String* key) { - Heap* heap = GetHeap(); // Check access rights if needed. - if (IsAccessCheckNeeded() && - !heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) { - heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); - return false; + if (IsAccessCheckNeeded()) { + Heap* heap = GetHeap(); + if (!heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) { + heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); + return false; + } } LookupResult result; @@ -8674,7 +8711,6 @@ int StringDictionary::FindEntry(String* key) { template MaybeObject* HashTable::EnsureCapacity(int n, Key key) { - Heap* heap = GetHeap(); int capacity = Capacity(); int nof = NumberOfElements() + n; int nod = NumberOfDeletedElements(); @@ -8688,7 +8724,7 @@ MaybeObject* HashTable::EnsureCapacity(int n, Key key) { const int kMinCapacityForPretenure = 256; bool pretenure = - (capacity > kMinCapacityForPretenure) && !heap->InNewSpace(this); + (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this); Object* obj; { MaybeObject* maybe_obj = Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); @@ -8820,7 +8856,6 @@ int HashTable::FindEntry(uint32_t); // Collates undefined and unexisting elements below limit from position // zero of the elements. The object stays in Dictionary mode. MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { - Heap* heap = GetHeap(); ASSERT(HasDictionaryElements()); // Must stay in dictionary mode, either because of requires_slow_elements, // or because we are not going to sort (and therefore compact) all of the @@ -8830,7 +8865,7 @@ MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { if (limit > static_cast(Smi::kMaxValue)) { // Allocate space for result before we start mutating the object. Object* new_double; - { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0); + { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0); if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; } result_double = HeapNumber::cast(new_double); @@ -8890,6 +8925,7 @@ MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { uint32_t result = pos; PropertyDetails no_details = PropertyDetails(NONE, NORMAL); + Heap* heap = GetHeap(); while (undefs > 0) { if (pos > static_cast(Smi::kMaxValue)) { // Adding an entry with the key beyond smi-range requires @@ -8919,9 +8955,10 @@ MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { // If the object is in dictionary mode, it is converted to fast elements // mode. MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { - Heap* heap = GetHeap(); ASSERT(!HasExternalArrayElements()); + Heap* heap = GetHeap(); + if (HasDictionaryElements()) { // Convert to fast elements containing only the existing properties. // Ordering is irrelevant, since we are going to sort anyway. @@ -9175,9 +9212,9 @@ JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { ASSERT(!HasFastProperties()); - Heap* heap = GetHeap(); int entry = property_dictionary()->FindEntry(name); if (entry == StringDictionary::kNotFound) { + Heap* heap = GetHeap(); Object* cell; { MaybeObject* maybe_cell = heap->AllocateJSGlobalPropertyCell(heap->the_hole_value()); @@ -9352,10 +9389,9 @@ MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) { Object* CompilationCacheTable::Lookup(String* src) { - Heap* heap = GetHeap(); StringKey key(src); int entry = FindEntry(&key); - if (entry == kNotFound) return heap->undefined_value(); + if (entry == kNotFound) return GetHeap()->undefined_value(); return get(EntryToIndex(entry) + 1); } @@ -9372,10 +9408,9 @@ Object* CompilationCacheTable::LookupEval(String* src, Object* CompilationCacheTable::LookupRegExp(String* src, JSRegExp::Flags flags) { - Heap* heap = GetHeap(); RegExpKey key(src, flags); int entry = FindEntry(&key); - if (entry == kNotFound) return heap->undefined_value(); + if (entry == kNotFound) return GetHeap()->undefined_value(); return get(EntryToIndex(entry) + 1); } @@ -9495,10 +9530,9 @@ class SymbolsKey : public HashTableKey { Object* MapCache::Lookup(FixedArray* array) { - Heap* heap = GetHeap(); SymbolsKey key(array); int entry = FindEntry(&key); - if (entry == kNotFound) return heap->undefined_value(); + if (entry == kNotFound) return GetHeap()->undefined_value(); return get(EntryToIndex(entry) + 1); } @@ -9854,7 +9888,6 @@ void Dictionary::CopyKeysTo(FixedArray* storage) { // Backwards lookup (slow). template Object* Dictionary::SlowReverseLookup(Object* value) { - Heap* heap = Dictionary::GetHeap(); int capacity = HashTable::Capacity(); for (int i = 0; i < capacity; i++) { Object* k = HashTable::KeyAt(i); @@ -9866,13 +9899,13 @@ Object* Dictionary::SlowReverseLookup(Object* value) { if (e == value) return k; } } + Heap* heap = Dictionary::GetHeap(); return heap->undefined_value(); } MaybeObject* StringDictionary::TransformPropertiesToFastFor( JSObject* obj, int unused_property_fields) { - Heap* heap = GetHeap(); // Make sure we preserve dictionary representation if there are too many // descriptors. if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj; @@ -9892,6 +9925,8 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( int instance_descriptor_length = 0; int number_of_fields = 0; + Heap* heap = GetHeap(); + // Compute the length of the instance descriptor. int capacity = Capacity(); for (int i = 0; i < capacity; i++) { @@ -10020,12 +10055,11 @@ bool DebugInfo::HasBreakPoint(int code_position) { // Get the break point info object for this code position. Object* DebugInfo::GetBreakPointInfo(int code_position) { - Heap* heap = GetHeap(); // Find the index of the break point info object for this code position. int index = GetBreakPointInfoIndex(code_position); // Return the break point info object if any. - if (index == kNoBreakPointInfo) return heap->undefined_value(); + if (index == kNoBreakPointInfo) return GetHeap()->undefined_value(); return BreakPointInfo::cast(break_points()->get(index)); } @@ -10098,10 +10132,9 @@ void DebugInfo::SetBreakPoint(Handle debug_info, // Get the break point objects for a code position. Object* DebugInfo::GetBreakPointObjects(int code_position) { - Heap* heap = GetHeap(); Object* break_point_info = GetBreakPointInfo(code_position); if (break_point_info->IsUndefined()) { - return heap->undefined_value(); + return GetHeap()->undefined_value(); } return BreakPointInfo::cast(break_point_info)->break_point_objects(); } @@ -10124,7 +10157,7 @@ int DebugInfo::GetBreakPointCount() { Object* DebugInfo::FindBreakPointInfo(Handle debug_info, Handle break_point_object) { - Heap* heap = Isolate::Current()->heap(); + Heap* heap = debug_info->GetHeap(); if (debug_info->break_points()->IsUndefined()) return heap->undefined_value(); for (int i = 0; i < debug_info->break_points()->length(); i++) { if (!debug_info->break_points()->get(i)->IsUndefined()) { diff --git a/src/objects.h b/src/objects.h index 96e5cb692..102429897 100644 --- a/src/objects.h +++ b/src/objects.h @@ -3487,6 +3487,10 @@ class Code: public HeapObject { void CodeVerify(); #endif + // Returns the isolate/heap this code object belongs to. + inline Isolate* isolate(); + inline Heap* heap(); + // Max loop nesting marker used to postpose OSR. We don't take loop // nesting that is deeper than 5 levels into account. static const int kMaxLoopNestingMarker = 6; @@ -6009,6 +6013,10 @@ class JSGlobalPropertyCell: public HeapObject { kValueOffset + kPointerSize, kSize> BodyDescriptor; + // Returns the isolate/heap this cell object belongs to. + inline Isolate* isolate(); + inline Heap* heap(); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell); }; -- 2.34.1