2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef ObjectAllocationProfile_h
27 #define ObjectAllocationProfile_h
30 #include "JSGlobalObject.h"
31 #include "ObjectPrototype.h"
32 #include "SlotVisitor.h"
33 #include "WriteBarrier.h"
37 class ObjectAllocationProfile
{
38 friend class LLIntOffsetsExtractor
;
40 static ptrdiff_t offsetOfAllocator() { return OBJECT_OFFSETOF(ObjectAllocationProfile
, m_allocator
); }
41 static ptrdiff_t offsetOfStructure() { return OBJECT_OFFSETOF(ObjectAllocationProfile
, m_structure
); }
43 ObjectAllocationProfile()
48 bool isNull() { return !m_allocator
; }
50 void initialize(VM
& vm
, JSCell
* owner
, JSObject
* prototype
, unsigned inferredInlineCapacity
)
55 unsigned inlineCapacity
= 0;
56 if (inferredInlineCapacity
< JSFinalObject::defaultInlineCapacity()) {
57 // Try to shrink the object based on static analysis.
58 inferredInlineCapacity
+= possibleDefaultPropertyCount(vm
, prototype
);
60 if (!inferredInlineCapacity
) {
61 // Empty objects are rare, so most likely the static analyzer just didn't
62 // see the real initializer function. This can happen with helper functions.
63 inferredInlineCapacity
= JSFinalObject::defaultInlineCapacity();
64 } else if (inferredInlineCapacity
> JSFinalObject::defaultInlineCapacity()) {
65 // Default properties are weak guesses, so don't allow them to turn a small
66 // object into a large object.
67 inferredInlineCapacity
= JSFinalObject::defaultInlineCapacity();
70 inlineCapacity
= inferredInlineCapacity
;
71 ASSERT(inlineCapacity
< JSFinalObject::maxInlineCapacity());
73 // Normal or large object.
74 inlineCapacity
= inferredInlineCapacity
;
75 if (inlineCapacity
> JSFinalObject::maxInlineCapacity())
76 inlineCapacity
= JSFinalObject::maxInlineCapacity();
79 ASSERT(inlineCapacity
> 0);
80 ASSERT(inlineCapacity
<= JSFinalObject::maxInlineCapacity());
82 size_t allocationSize
= JSFinalObject::allocationSize(inlineCapacity
);
83 MarkedAllocator
* allocator
= &vm
.heap
.allocatorForObjectWithoutDestructor(allocationSize
);
84 ASSERT(allocator
->cellSize());
86 // Take advantage of extra inline capacity available in the size class.
87 size_t slop
= (allocator
->cellSize() - allocationSize
) / sizeof(WriteBarrier
<Unknown
>);
88 inlineCapacity
+= slop
;
89 if (inlineCapacity
> JSFinalObject::maxInlineCapacity())
90 inlineCapacity
= JSFinalObject::maxInlineCapacity();
92 m_allocator
= allocator
;
93 m_structure
.set(vm
, owner
,
94 vm
.prototypeMap
.emptyObjectStructureForPrototype(prototype
, inlineCapacity
));
97 Structure
* structure() { return m_structure
.get(); }
98 unsigned inlineCapacity() { return m_structure
->inlineCapacity(); }
107 void visitAggregate(SlotVisitor
& visitor
)
109 visitor
.append(&m_structure
);
114 unsigned possibleDefaultPropertyCount(VM
& vm
, JSObject
* prototype
)
116 if (prototype
== prototype
->globalObject()->objectPrototype())
120 PropertyNameArray
propertyNameArray(&vm
);
121 prototype
->structure()->getPropertyNamesFromStructure(vm
, propertyNameArray
, ExcludeDontEnumProperties
);
122 PropertyNameArrayData::PropertyNameVector
& propertyNameVector
= propertyNameArray
.data()->propertyNameVector();
123 for (size_t i
= 0; i
< propertyNameVector
.size(); ++i
) {
124 JSValue value
= prototype
->getDirect(vm
, propertyNameVector
[i
]);
126 // Functions are common, and are usually class-level objects that are not overridden.
127 if (jsDynamicCast
<JSFunction
*>(value
))
136 MarkedAllocator
* m_allocator
; // Precomputed to make things easier for generated code.
137 WriteBarrier
<Structure
> m_structure
;
142 #endif // ObjectAllocationProfile_h