| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 2949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2960 MaybeObject* Heap::AllocateBox(Object* value, PretenureFlag pretenure) { | 2960 MaybeObject* Heap::AllocateBox(Object* value, PretenureFlag pretenure) { |
| 2961 Box* result; | 2961 Box* result; |
| 2962 MaybeObject* maybe_result = AllocateStruct(BOX_TYPE); | 2962 MaybeObject* maybe_result = AllocateStruct(BOX_TYPE); |
| 2963 if (!maybe_result->To(&result)) return maybe_result; | 2963 if (!maybe_result->To(&result)) return maybe_result; |
| 2964 result->set_value(value); | 2964 result->set_value(value); |
| 2965 return result; | 2965 return result; |
| 2966 } | 2966 } |
| 2967 | 2967 |
| 2968 | 2968 |
| 2969 MaybeObject* Heap::AllocateAllocationSite() { | 2969 MaybeObject* Heap::AllocateAllocationSite() { |
| 2970 Object* result; | 2970 AllocationSite* site; |
| 2971 MaybeObject* maybe_result = Allocate(allocation_site_map(), | 2971 MaybeObject* maybe_result = Allocate(allocation_site_map(), |
| 2972 OLD_POINTER_SPACE); | 2972 OLD_POINTER_SPACE); |
| 2973 if (!maybe_result->ToObject(&result)) return maybe_result; | 2973 if (!maybe_result->To(&site)) return maybe_result; |
| 2974 AllocationSite* site = AllocationSite::cast(result); | |
| 2975 site->Initialize(); | 2974 site->Initialize(); |
| 2976 | 2975 |
| 2977 // Link the site | 2976 // Link the site |
| 2978 site->set_weak_next(allocation_sites_list()); | 2977 site->set_weak_next(allocation_sites_list()); |
| 2979 set_allocation_sites_list(site); | 2978 set_allocation_sites_list(site); |
| 2980 return result; | 2979 return site; |
| 2981 } | 2980 } |
| 2982 | 2981 |
| 2983 | 2982 |
| 2984 MaybeObject* Heap::CreateOddball(const char* to_string, | 2983 MaybeObject* Heap::CreateOddball(const char* to_string, |
| 2985 Object* to_number, | 2984 Object* to_number, |
| 2986 byte kind) { | 2985 byte kind) { |
| 2987 Object* result; | 2986 Object* result; |
| 2988 { MaybeObject* maybe_result = Allocate(oddball_map(), OLD_POINTER_SPACE); | 2987 { MaybeObject* maybe_result = Allocate(oddball_map(), OLD_POINTER_SPACE); |
| 2989 if (!maybe_result->ToObject(&result)) return maybe_result; | 2988 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2990 } | 2989 } |
| (...skipping 1926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4917 global->set_map(new_map); | 4916 global->set_map(new_map); |
| 4918 global->set_properties(dictionary); | 4917 global->set_properties(dictionary); |
| 4919 | 4918 |
| 4920 // Make sure result is a global object with properties in dictionary. | 4919 // Make sure result is a global object with properties in dictionary. |
| 4921 ASSERT(global->IsGlobalObject()); | 4920 ASSERT(global->IsGlobalObject()); |
| 4922 ASSERT(!global->HasFastProperties()); | 4921 ASSERT(!global->HasFastProperties()); |
| 4923 return global; | 4922 return global; |
| 4924 } | 4923 } |
| 4925 | 4924 |
| 4926 | 4925 |
| 4927 MaybeObject* Heap::CopyJSObject(JSObject* source) { | 4926 MaybeObject* Heap::CopyJSObject(JSObject* source, AllocationSite* site) { |
| 4928 // Never used to copy functions. If functions need to be copied we | 4927 // Never used to copy functions. If functions need to be copied we |
| 4929 // have to be careful to clear the literals array. | 4928 // have to be careful to clear the literals array. |
| 4930 SLOW_ASSERT(!source->IsJSFunction()); | 4929 SLOW_ASSERT(!source->IsJSFunction()); |
| 4931 | 4930 |
| 4932 // Make the clone. | 4931 // Make the clone. |
| 4933 Map* map = source->map(); | 4932 Map* map = source->map(); |
| 4934 int object_size = map->instance_size(); | 4933 int object_size = map->instance_size(); |
| 4935 Object* clone; | 4934 Object* clone; |
| 4936 | 4935 |
| 4936 ASSERT(site == NULL || (AllocationSite::CanTrack(map->instance_type()) && |
| 4937 map->instance_type() == JS_ARRAY_TYPE)); |
| 4938 |
| 4937 WriteBarrierMode wb_mode = UPDATE_WRITE_BARRIER; | 4939 WriteBarrierMode wb_mode = UPDATE_WRITE_BARRIER; |
| 4938 | 4940 |
| 4939 // If we're forced to always allocate, we use the general allocation | 4941 // If we're forced to always allocate, we use the general allocation |
| 4940 // functions which may leave us with an object in old space. | 4942 // functions which may leave us with an object in old space. |
| 4941 if (always_allocate()) { | 4943 if (always_allocate()) { |
| 4942 { MaybeObject* maybe_clone = | 4944 { MaybeObject* maybe_clone = |
| 4943 AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE); | 4945 AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE); |
| 4944 if (!maybe_clone->ToObject(&clone)) return maybe_clone; | 4946 if (!maybe_clone->ToObject(&clone)) return maybe_clone; |
| 4945 } | 4947 } |
| 4946 Address clone_address = HeapObject::cast(clone)->address(); | 4948 Address clone_address = HeapObject::cast(clone)->address(); |
| 4947 CopyBlock(clone_address, | 4949 CopyBlock(clone_address, |
| 4948 source->address(), | 4950 source->address(), |
| 4949 object_size); | 4951 object_size); |
| 4950 // Update write barrier for all fields that lie beyond the header. | 4952 // Update write barrier for all fields that lie beyond the header. |
| 4951 RecordWrites(clone_address, | 4953 RecordWrites(clone_address, |
| 4952 JSObject::kHeaderSize, | 4954 JSObject::kHeaderSize, |
| 4953 (object_size - JSObject::kHeaderSize) / kPointerSize); | 4955 (object_size - JSObject::kHeaderSize) / kPointerSize); |
| 4954 } else { | 4956 } else { |
| 4955 wb_mode = SKIP_WRITE_BARRIER; | 4957 wb_mode = SKIP_WRITE_BARRIER; |
| 4956 | 4958 |
| 4957 { MaybeObject* maybe_clone = new_space_.AllocateRaw(object_size); | 4959 { int adjusted_object_size = site != NULL |
| 4960 ? object_size + AllocationMemento::kSize |
| 4961 : object_size; |
| 4962 MaybeObject* maybe_clone = new_space_.AllocateRaw(adjusted_object_size); |
| 4958 if (!maybe_clone->ToObject(&clone)) return maybe_clone; | 4963 if (!maybe_clone->ToObject(&clone)) return maybe_clone; |
| 4959 } | 4964 } |
| 4960 SLOW_ASSERT(InNewSpace(clone)); | 4965 SLOW_ASSERT(InNewSpace(clone)); |
| 4961 // Since we know the clone is allocated in new space, we can copy | 4966 // Since we know the clone is allocated in new space, we can copy |
| 4962 // the contents without worrying about updating the write barrier. | 4967 // the contents without worrying about updating the write barrier. |
| 4963 CopyBlock(HeapObject::cast(clone)->address(), | 4968 CopyBlock(HeapObject::cast(clone)->address(), |
| 4964 source->address(), | 4969 source->address(), |
| 4965 object_size); | 4970 object_size); |
| 4971 |
| 4972 if (site != NULL) { |
| 4973 AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>( |
| 4974 reinterpret_cast<Address>(clone) + object_size); |
| 4975 alloc_memento->set_map_no_write_barrier(allocation_memento_map()); |
| 4976 ASSERT(site->map() == allocation_site_map()); |
| 4977 alloc_memento->set_allocation_site(site, SKIP_WRITE_BARRIER); |
| 4978 } |
| 4966 } | 4979 } |
| 4967 | 4980 |
| 4968 SLOW_ASSERT( | 4981 SLOW_ASSERT( |
| 4969 JSObject::cast(clone)->GetElementsKind() == source->GetElementsKind()); | |
| 4970 FixedArrayBase* elements = FixedArrayBase::cast(source->elements()); | |
| 4971 FixedArray* properties = FixedArray::cast(source->properties()); | |
| 4972 // Update elements if necessary. | |
| 4973 if (elements->length() > 0) { | |
| 4974 Object* elem; | |
| 4975 { MaybeObject* maybe_elem; | |
| 4976 if (elements->map() == fixed_cow_array_map()) { | |
| 4977 maybe_elem = FixedArray::cast(elements); | |
| 4978 } else if (source->HasFastDoubleElements()) { | |
| 4979 maybe_elem = CopyFixedDoubleArray(FixedDoubleArray::cast(elements)); | |
| 4980 } else { | |
| 4981 maybe_elem = CopyFixedArray(FixedArray::cast(elements)); | |
| 4982 } | |
| 4983 if (!maybe_elem->ToObject(&elem)) return maybe_elem; | |
| 4984 } | |
| 4985 JSObject::cast(clone)->set_elements(FixedArrayBase::cast(elem), wb_mode); | |
| 4986 } | |
| 4987 // Update properties if necessary. | |
| 4988 if (properties->length() > 0) { | |
| 4989 Object* prop; | |
| 4990 { MaybeObject* maybe_prop = CopyFixedArray(properties); | |
| 4991 if (!maybe_prop->ToObject(&prop)) return maybe_prop; | |
| 4992 } | |
| 4993 JSObject::cast(clone)->set_properties(FixedArray::cast(prop), wb_mode); | |
| 4994 } | |
| 4995 // Return the new clone. | |
| 4996 return clone; | |
| 4997 } | |
| 4998 | |
| 4999 | |
| 5000 MaybeObject* Heap::CopyJSObjectWithAllocationSite( | |
| 5001 JSObject* source, | |
| 5002 AllocationSite* site) { | |
| 5003 // Never used to copy functions. If functions need to be copied we | |
| 5004 // have to be careful to clear the literals array. | |
| 5005 SLOW_ASSERT(!source->IsJSFunction()); | |
| 5006 | |
| 5007 // Make the clone. | |
| 5008 Map* map = source->map(); | |
| 5009 int object_size = map->instance_size(); | |
| 5010 Object* clone; | |
| 5011 | |
| 5012 ASSERT(AllocationSite::CanTrack(map->instance_type())); | |
| 5013 ASSERT(map->instance_type() == JS_ARRAY_TYPE); | |
| 5014 WriteBarrierMode wb_mode = UPDATE_WRITE_BARRIER; | |
| 5015 | |
| 5016 // If we're forced to always allocate, we use the general allocation | |
| 5017 // functions which may leave us with an object in old space. | |
| 5018 int adjusted_object_size = object_size; | |
| 5019 if (always_allocate()) { | |
| 5020 // We'll only track origin if we are certain to allocate in new space | |
| 5021 const int kMinFreeNewSpaceAfterGC = InitialSemiSpaceSize() * 3/4; | |
| 5022 if ((object_size + AllocationMemento::kSize) < kMinFreeNewSpaceAfterGC) { | |
| 5023 adjusted_object_size += AllocationMemento::kSize; | |
| 5024 } | |
| 5025 | |
| 5026 { MaybeObject* maybe_clone = | |
| 5027 AllocateRaw(adjusted_object_size, NEW_SPACE, OLD_POINTER_SPACE); | |
| 5028 if (!maybe_clone->ToObject(&clone)) return maybe_clone; | |
| 5029 } | |
| 5030 Address clone_address = HeapObject::cast(clone)->address(); | |
| 5031 CopyBlock(clone_address, | |
| 5032 source->address(), | |
| 5033 object_size); | |
| 5034 // Update write barrier for all fields that lie beyond the header. | |
| 5035 int write_barrier_offset = adjusted_object_size > object_size | |
| 5036 ? JSArray::kSize + AllocationMemento::kSize | |
| 5037 : JSObject::kHeaderSize; | |
| 5038 if (((object_size - write_barrier_offset) / kPointerSize) > 0) { | |
| 5039 RecordWrites(clone_address, | |
| 5040 write_barrier_offset, | |
| 5041 (object_size - write_barrier_offset) / kPointerSize); | |
| 5042 } | |
| 5043 | |
| 5044 // Track allocation site information, if we failed to allocate it inline. | |
| 5045 if (InNewSpace(clone) && | |
| 5046 adjusted_object_size == object_size) { | |
| 5047 MaybeObject* maybe_alloc_memento = | |
| 5048 AllocateStruct(ALLOCATION_MEMENTO_TYPE); | |
| 5049 AllocationMemento* alloc_memento; | |
| 5050 if (maybe_alloc_memento->To(&alloc_memento)) { | |
| 5051 alloc_memento->set_map_no_write_barrier(allocation_memento_map()); | |
| 5052 ASSERT(site->map() == allocation_site_map()); | |
| 5053 alloc_memento->set_allocation_site(site, SKIP_WRITE_BARRIER); | |
| 5054 } | |
| 5055 } | |
| 5056 } else { | |
| 5057 wb_mode = SKIP_WRITE_BARRIER; | |
| 5058 adjusted_object_size += AllocationMemento::kSize; | |
| 5059 | |
| 5060 { MaybeObject* maybe_clone = new_space_.AllocateRaw(adjusted_object_size); | |
| 5061 if (!maybe_clone->ToObject(&clone)) return maybe_clone; | |
| 5062 } | |
| 5063 SLOW_ASSERT(InNewSpace(clone)); | |
| 5064 // Since we know the clone is allocated in new space, we can copy | |
| 5065 // the contents without worrying about updating the write barrier. | |
| 5066 CopyBlock(HeapObject::cast(clone)->address(), | |
| 5067 source->address(), | |
| 5068 object_size); | |
| 5069 } | |
| 5070 | |
| 5071 if (adjusted_object_size > object_size) { | |
| 5072 AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>( | |
| 5073 reinterpret_cast<Address>(clone) + object_size); | |
| 5074 alloc_memento->set_map_no_write_barrier(allocation_memento_map()); | |
| 5075 ASSERT(site->map() == allocation_site_map()); | |
| 5076 alloc_memento->set_allocation_site(site, SKIP_WRITE_BARRIER); | |
| 5077 } | |
| 5078 | |
| 5079 SLOW_ASSERT( | |
| 5080 JSObject::cast(clone)->GetElementsKind() == source->GetElementsKind()); | 4982 JSObject::cast(clone)->GetElementsKind() == source->GetElementsKind()); |
| 5081 FixedArrayBase* elements = FixedArrayBase::cast(source->elements()); | 4983 FixedArrayBase* elements = FixedArrayBase::cast(source->elements()); |
| 5082 FixedArray* properties = FixedArray::cast(source->properties()); | 4984 FixedArray* properties = FixedArray::cast(source->properties()); |
| 5083 // Update elements if necessary. | 4985 // Update elements if necessary. |
| 5084 if (elements->length() > 0) { | 4986 if (elements->length() > 0) { |
| 5085 Object* elem; | 4987 Object* elem; |
| 5086 { MaybeObject* maybe_elem; | 4988 { MaybeObject* maybe_elem; |
| 5087 if (elements->map() == fixed_cow_array_map()) { | 4989 if (elements->map() == fixed_cow_array_map()) { |
| 5088 maybe_elem = FixedArray::cast(elements); | 4990 maybe_elem = FixedArray::cast(elements); |
| 5089 } else if (source->HasFastDoubleElements()) { | 4991 } else if (source->HasFastDoubleElements()) { |
| (...skipping 2995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8085 if (FLAG_concurrent_recompilation) { | 7987 if (FLAG_concurrent_recompilation) { |
| 8086 heap_->relocation_mutex_->Lock(); | 7988 heap_->relocation_mutex_->Lock(); |
| 8087 #ifdef DEBUG | 7989 #ifdef DEBUG |
| 8088 heap_->relocation_mutex_locked_by_optimizer_thread_ = | 7990 heap_->relocation_mutex_locked_by_optimizer_thread_ = |
| 8089 heap_->isolate()->optimizing_compiler_thread()->IsOptimizerThread(); | 7991 heap_->isolate()->optimizing_compiler_thread()->IsOptimizerThread(); |
| 8090 #endif // DEBUG | 7992 #endif // DEBUG |
| 8091 } | 7993 } |
| 8092 } | 7994 } |
| 8093 | 7995 |
| 8094 } } // namespace v8::internal | 7996 } } // namespace v8::internal |
| OLD | NEW |