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