Speed up JSGlobalObject initialization by making some properties lazy
[WebKit-https.git] / Source / JavaScriptCore / runtime / Lookup.cpp
1 /*
2  *  Copyright (C) 2008, 2012, 2015-2016 Apple Inc. All rights reserved.
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Lesser General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public
15  *  License along with this library; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  */
19
20 #include "config.h"
21 #include "Lookup.h"
22
23 #include "Executable.h"
24 #include "GetterSetter.h"
25 #include "JSFunction.h"
26 #include "JSCInlines.h"
27
28 namespace JSC {
29
30 void reifyStaticAccessor(VM& vm, const HashTableValue& value, JSObject& thisObj, PropertyName propertyName)
31 {
32     JSGlobalObject* globalObject = thisObj.globalObject();
33     GetterSetter* accessor = GetterSetter::create(vm, globalObject);
34     if (value.accessorGetter()) {
35         String getterName = WTF::tryMakeString(ASCIILiteral("get "), String(*propertyName.publicName()));
36         if (!getterName)
37             return;
38         accessor->setGetter(vm, globalObject, value.attributes() & Builtin
39             ? JSFunction::createBuiltinFunction(vm, value.builtinAccessorGetterGenerator()(vm), globalObject, getterName)
40             : JSFunction::create(vm, globalObject, 0, getterName, value.accessorGetter()));
41     }
42     thisObj.putDirectNonIndexAccessor(vm, propertyName, accessor, attributesForStructure(value.attributes()));
43 }
44
45 bool setUpStaticFunctionSlot(ExecState* exec, const HashTableValue* entry, JSObject* thisObj, PropertyName propertyName, PropertySlot& slot)
46 {
47     ASSERT(thisObj->globalObject());
48     ASSERT(entry->attributes() & BuiltinOrFunctionOrAccessorOrLazyProperty);
49     VM& vm = exec->vm();
50     unsigned attributes;
51     bool isAccessor = entry->attributes() & Accessor;
52     PropertyOffset offset = thisObj->getDirectOffset(vm, propertyName, attributes);
53
54     if (!isValidOffset(offset)) {
55         // If a property is ever deleted from an object with a static table, then we reify
56         // all static functions at that time - after this we shouldn't be re-adding anything.
57         if (thisObj->staticFunctionsReified())
58             return false;
59
60         if (entry->attributes() & Builtin)
61             thisObj->putDirectBuiltinFunction(vm, thisObj->globalObject(), propertyName, entry->builtinGenerator()(vm), attributesForStructure(entry->attributes()));
62         else if (entry->attributes() & Function) {
63             thisObj->putDirectNativeFunction(
64                 vm, thisObj->globalObject(), propertyName, entry->functionLength(),
65                 entry->function(), entry->intrinsic(), attributesForStructure(entry->attributes()));
66         } else if (isAccessor)
67             reifyStaticAccessor(vm, *entry, *thisObj, propertyName);
68         else if (entry->attributes() & CellProperty) {
69             LazyCellProperty* property = bitwise_cast<LazyCellProperty*>(
70                 bitwise_cast<char*>(thisObj) + entry->lazyCellPropertyOffset());
71             JSCell* result = property->get(thisObj);
72             thisObj->putDirect(vm, propertyName, result, attributesForStructure(entry->attributes()));
73         } else if (entry->attributes() & ClassStructure) {
74             LazyClassStructure* structure = bitwise_cast<LazyClassStructure*>(
75                 bitwise_cast<char*>(thisObj) + entry->lazyClassStructureOffset());
76             structure->get(jsCast<JSGlobalObject*>(thisObj));
77         } else if (entry->attributes() & PropertyCallback) {
78             JSValue result = entry->lazyPropertyCallback()(vm, thisObj);
79             thisObj->putDirect(vm, propertyName, result, attributesForStructure(entry->attributes()));
80         } else
81             RELEASE_ASSERT_NOT_REACHED();
82
83         offset = thisObj->getDirectOffset(vm, propertyName, attributes);
84         RELEASE_ASSERT(isValidOffset(offset));
85     }
86
87     if (isAccessor)
88         slot.setCacheableGetterSlot(thisObj, attributes, jsCast<GetterSetter*>(thisObj->getDirect(offset)), offset);
89     else
90         slot.setValue(thisObj, attributes, thisObj->getDirect(offset), offset);
91     return true;
92 }
93
94 } // namespace JSC