Speed up JSGlobalObject initialization by making some properties lazy
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 May 2016 21:21:36 +0000 (21:21 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 May 2016 21:21:36 +0000 (21:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=157045

Source/JavaScriptCore:

Reviewed by Keith Miller.

This makes about half of JSGlobalObject's state lazy. There are three categories of
state in JSGlobalObject:

1) C++ fields in JSGlobalObject.
2) JS object properties in JSGlobalObject's JSObject superclass.
3) JS variables in JSGlobalObject's JSSegmentedVariableObject superclass.

State held in JS variables cannot yet be made lazy. That's why this patch only goes
half-way.

State in JS object properties can be made lazy if we move it to the static property
hashtable. JSGlobalObject already had one of those. This patch makes static property
hashtables a lot more powerful, by adding three new kinds of static properties. These
new kinds allow us to make almost all of JSGlobalObject's object properties lazy.

State in C++ fields can now be made lazy thanks in part to WTF's support for stateless
lambdas. You can of course make anything lazy by hand, but there are many C++ fields in
JSGlobalObject and we are adding more all the time. We don't want to require that each
of these has a getter with an initialization check and a corresponding out-of-line slow
path that does the initialization. We want this kind of boilerplate to be handled by
some abstractions.

The primary abstraction introduced in this patch is LazyProperty<Type>. Currently, this
only works where Type is a subclass of JSCell. Such a property holds a pointer to Type.
You can use it like you would a WriteBarrier<Type>. It even has set() and get() methods,
so it's almost a drop-in replacement.

The key to LazyProperty<Type>'s power is that you can do this:

    class Bar {
        ...
        LazyProperty<Foo> m_foo;
    };
    ...
    m_foo.initLater(
        [] (const LazyProperty<Foo>::Initializer<Bar>& init) {
            init.set(Foo::create(init.vm, init.owner));
        });

This initLater() call requires that you pass a stateless lambda (see WTF changelog for
the definition). Miraculously, this initLater() call is guaranteed to compile to a store
of a pointer constant to m_foo, as in:

    movabsq 0xBLAH, %rax
    movq %rax, &m_foo

This magical pointer constant points to a callback that was generated by the template
instantiation of initLater(). That callback knows to call your stateless lambda, but
also does some other bookkeeping: it makes sure that you indeed initialized the property
inside the callback and it manages recursive initializations. It's totally legal to call
m_foo.get() inside the initLater() callback. If you do that before you call init.set(),
m_foo.get() will return null. This is an excellent escape hatch if we ever find
ourselves in a dependency cycle. I added this feature because I already had to create a
dependency cycle.

Note that using LazyProperties from DFG threads is super awkward. It's going to be hard
to get this right. The DFG thread cannot initialize those fields, so it has to make sure
that it does conservative things. But for some nodes this could mean adding a lot of new
logic, like NewTypedArray, which currently is written in such a way that it assumes that
we always have the typed array structure. Currently we take a two-fold approach: for
typed arrays we don't handle the NewTypedArray intrinsic if the structure isn't
initialized, and for everything else we don't make the properties lazy if the DFG needs
them. As we optimize this further we might need to teach the DFG to handle more lazy
properties. I tried to do this for RegExp but found it to be very confusing. With typed
arrays I got lucky.

There is also a somewhat more powerful construct called LazyClassStructure. We often
need to keep around the structure of some standard JS class, like Date. We also need to
make sure that the constructor ends up in the global object's property table. And we
often need to keep the original value of the constructor for ourselves. In this case, we
want to make sure that the creation of the structure-prototype-constructor constellation
is atomic. We don't want code to start looking at the structure if it points to a
prototype that doesn't have its "constructor" property set yet, for example.
LazyClassStructure solves this by abstracting that whole initialization. You provide the
callback that allocates everything, since we are super inconsistent about the way we
initialize things, but LazyClassStructure establishes the workflow and helps you not
mess up.

Finally, the new static hashtable attributes allow for all of this to work with the JS
property table:

PropertyCallback: if you use this attribute, the second column in the table should be
the name of a function to call to initialize this property. This is useful for things
like the Math property. The Math object turns out to be very expensive to allocate.
Delaying its allocation is super easy with the PropertyCallback attribute.

CellProperty: with this attribute the second column should be a C++ field name like
JSGlobalObject::m_evalErrorConstructor. The static hashtable will grab the offset of
this property, and when it needs to be initialized, Lookup will assume you have a
LazyProperty<JSCell> and call its get() method. It will initialize the property to
whatever get() returned. Note that it's legal to cast a LazyProperty<Anything> to
LazyProperty<JSCell> for the purpose of calling get() because the get() method will just
call whatever callback function pointer is encoded in the property and it does not need
to know anything about what type that callback will instantiate.

ClassStructure: with this attribute the second column should be a C++ field name. The
static hashtable will initialize the property by treating the field as a
LazyClassStructure and it will call get(). LazyClassStructure completely owns the whole
initialization workflow, so Lookup assumes that when LazyClassStructure::get() returns,
the property in question will already be set. By convention, we have LazyClassStructure
initialize the property with a pointer to the constructor, since that's how all of our
classes work: "globalObject.Date" points to the DateConstructor.

This is a 2x speed-up in JSGlobalObject initialization time in a microbenchmark that
calls our C API. This is a 1% speed-up on SunSpider and JSRegress.

Rolling this back in after fixing the function pointer alignment issue. The last version
relied on function pointers being aligned to a 4-byte boundary. We cannot rely on this,
especially since ARMv7 uses the low bit of function pointers as a tag to indicate the
instruction set. This version adds an extra indirection, so that
LazyProperty<>::m_pointer points to a pointer that points to the function. A pointer to
a pointer is guaranteed to be at least 4-byte aligned.

* API/JSCallbackFunction.cpp:
(JSC::JSCallbackFunction::create):
* API/ObjCCallbackFunction.h:
(JSC::ObjCCallbackFunction::impl):
* API/ObjCCallbackFunction.mm:
(JSC::ObjCCallbackFunction::ObjCCallbackFunction):
(JSC::ObjCCallbackFunction::create):
* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* create_hash_table:
* debugger/DebuggerScope.cpp:
(JSC::DebuggerScope::create):
(JSC::DebuggerScope::DebuggerScope):
* debugger/DebuggerScope.h:
(JSC::DebuggerScope::jsScope):
(JSC::DebuggerScope::create): Deleted.
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::set):
* dfg/DFGArrayMode.cpp:
(JSC::DFG::ArrayMode::originalArrayStructure):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleTypedArrayConstructor):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileNewTypedArray):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStructureRegistrationPhase.cpp:
(JSC::DFG::StructureRegistrationPhase::run):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
* runtime/ClonedArguments.cpp:
(JSC::ClonedArguments::getOwnPropertySlot):
(JSC::ClonedArguments::materializeSpecials):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/FunctionPrototype.cpp:
(JSC::functionProtoFuncToString):
* runtime/InternalFunction.cpp:
(JSC::InternalFunction::visitChildren):
(JSC::InternalFunction::name):
(JSC::InternalFunction::calculatedDisplayName):
(JSC::InternalFunction::createSubclassStructure):
* runtime/InternalFunction.h:
* runtime/JSBoundFunction.cpp:
(JSC::JSBoundFunction::finishCreation):
(JSC::JSBoundFunction::visitChildren):
* runtime/JSBoundSlotBaseFunction.cpp:
(JSC::JSBoundSlotBaseFunction::create):
* runtime/JSFunction.cpp:
(JSC::retrieveCallerFunction):
(JSC::getThrowTypeErrorGetterSetter):
(JSC::JSFunction::callerGetter):
(JSC::JSFunction::getOwnPropertySlot):
(JSC::JSFunction::defineOwnProperty):
* runtime/JSGenericTypedArrayViewConstructorInlines.h:
(JSC::constructGenericTypedArrayView):
* runtime/JSGlobalObject.cpp:
(JSC::createProxyProperty):
(JSC::createJSONProperty):
(JSC::createMathProperty):
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::stringPrototypeChainIsSane):
(JSC::JSGlobalObject::resetPrototype):
(JSC::JSGlobalObject::visitChildren):
(JSC::JSGlobalObject::toThis):
(JSC::JSGlobalObject::getOwnPropertySlot):
(JSC::JSGlobalObject::createThrowTypeError): Deleted.
(JSC::JSGlobalObject::createThrowTypeErrorArgumentsAndCaller): Deleted.
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::objectConstructor):
(JSC::JSGlobalObject::promiseConstructor):
(JSC::JSGlobalObject::internalPromiseConstructor):
(JSC::JSGlobalObject::evalErrorConstructor):
(JSC::JSGlobalObject::rangeErrorConstructor):
(JSC::JSGlobalObject::referenceErrorConstructor):
(JSC::JSGlobalObject::syntaxErrorConstructor):
(JSC::JSGlobalObject::typeErrorConstructor):
(JSC::JSGlobalObject::URIErrorConstructor):
(JSC::JSGlobalObject::nullGetterFunction):
(JSC::JSGlobalObject::nullSetterFunction):
(JSC::JSGlobalObject::callFunction):
(JSC::JSGlobalObject::applyFunction):
(JSC::JSGlobalObject::definePropertyFunction):
(JSC::JSGlobalObject::arrayProtoValuesFunction):
(JSC::JSGlobalObject::initializePromiseFunction):
(JSC::JSGlobalObject::newPromiseCapabilityFunction):
(JSC::JSGlobalObject::functionProtoHasInstanceSymbolFunction):
(JSC::JSGlobalObject::regExpProtoExecFunction):
(JSC::JSGlobalObject::regExpProtoSymbolReplaceFunction):
(JSC::JSGlobalObject::regExpProtoGlobalGetter):
(JSC::JSGlobalObject::regExpProtoUnicodeGetter):
(JSC::JSGlobalObject::throwTypeErrorGetterSetter):
(JSC::JSGlobalObject::throwTypeErrorArgumentsAndCallerGetterSetter):
(JSC::JSGlobalObject::moduleLoader):
(JSC::JSGlobalObject::objectPrototype):
(JSC::JSGlobalObject::functionPrototype):
(JSC::JSGlobalObject::arrayPrototype):
(JSC::JSGlobalObject::booleanPrototype):
(JSC::JSGlobalObject::stringPrototype):
(JSC::JSGlobalObject::symbolPrototype):
(JSC::JSGlobalObject::numberPrototype):
(JSC::JSGlobalObject::datePrototype):
(JSC::JSGlobalObject::regExpPrototype):
(JSC::JSGlobalObject::errorPrototype):
(JSC::JSGlobalObject::iteratorPrototype):
(JSC::JSGlobalObject::generatorFunctionPrototype):
(JSC::JSGlobalObject::generatorPrototype):
(JSC::JSGlobalObject::debuggerScopeStructure):
(JSC::JSGlobalObject::withScopeStructure):
(JSC::JSGlobalObject::strictEvalActivationStructure):
(JSC::JSGlobalObject::activationStructure):
(JSC::JSGlobalObject::moduleEnvironmentStructure):
(JSC::JSGlobalObject::directArgumentsStructure):
(JSC::JSGlobalObject::scopedArgumentsStructure):
(JSC::JSGlobalObject::clonedArgumentsStructure):
(JSC::JSGlobalObject::isOriginalArrayStructure):
(JSC::JSGlobalObject::booleanObjectStructure):
(JSC::JSGlobalObject::callbackConstructorStructure):
(JSC::JSGlobalObject::callbackFunctionStructure):
(JSC::JSGlobalObject::callbackObjectStructure):
(JSC::JSGlobalObject::propertyNameIteratorStructure):
(JSC::JSGlobalObject::objcCallbackFunctionStructure):
(JSC::JSGlobalObject::objcWrapperObjectStructure):
(JSC::JSGlobalObject::dateStructure):
(JSC::JSGlobalObject::nullPrototypeObjectStructure):
(JSC::JSGlobalObject::errorStructure):
(JSC::JSGlobalObject::calleeStructure):
(JSC::JSGlobalObject::functionStructure):
(JSC::JSGlobalObject::boundFunctionStructure):
(JSC::JSGlobalObject::boundSlotBaseFunctionStructure):
(JSC::JSGlobalObject::getterSetterStructure):
(JSC::JSGlobalObject::nativeStdFunctionStructure):
(JSC::JSGlobalObject::namedFunctionStructure):
(JSC::JSGlobalObject::functionNameOffset):
(JSC::JSGlobalObject::numberObjectStructure):
(JSC::JSGlobalObject::privateNameStructure):
(JSC::JSGlobalObject::mapStructure):
(JSC::JSGlobalObject::regExpStructure):
(JSC::JSGlobalObject::generatorFunctionStructure):
(JSC::JSGlobalObject::setStructure):
(JSC::JSGlobalObject::stringObjectStructure):
(JSC::JSGlobalObject::symbolObjectStructure):
(JSC::JSGlobalObject::iteratorResultObjectStructure):
(JSC::JSGlobalObject::lazyTypedArrayStructure):
(JSC::JSGlobalObject::typedArrayStructure):
(JSC::JSGlobalObject::typedArrayStructureConcurrently):
(JSC::JSGlobalObject::isOriginalTypedArrayStructure):
(JSC::JSGlobalObject::typedArrayConstructor):
(JSC::JSGlobalObject::actualPointerFor):
(JSC::JSGlobalObject::internalFunctionStructure): Deleted.
* runtime/JSNativeStdFunction.cpp:
(JSC::JSNativeStdFunction::create):
* runtime/JSWithScope.cpp:
(JSC::JSWithScope::create):
(JSC::JSWithScope::visitChildren):
(JSC::JSWithScope::createStructure):
(JSC::JSWithScope::JSWithScope):
* runtime/JSWithScope.h:
(JSC::JSWithScope::object):
(JSC::JSWithScope::create): Deleted.
(JSC::JSWithScope::createStructure): Deleted.
(JSC::JSWithScope::JSWithScope): Deleted.
* runtime/LazyClassStructure.cpp: Added.
(JSC::LazyClassStructure::Initializer::Initializer):
(JSC::LazyClassStructure::Initializer::setPrototype):
(JSC::LazyClassStructure::Initializer::setStructure):
(JSC::LazyClassStructure::Initializer::setConstructor):
(JSC::LazyClassStructure::visit):
(JSC::LazyClassStructure::dump):
* runtime/LazyClassStructure.h: Added.
(JSC::LazyClassStructure::LazyClassStructure):
(JSC::LazyClassStructure::get):
(JSC::LazyClassStructure::prototype):
(JSC::LazyClassStructure::constructor):
(JSC::LazyClassStructure::getConcurrently):
(JSC::LazyClassStructure::prototypeConcurrently):
(JSC::LazyClassStructure::constructorConcurrently):
* runtime/LazyClassStructureInlines.h: Added.
(JSC::LazyClassStructure::initLater):
* runtime/LazyProperty.h: Added.
(JSC::LazyProperty::Initializer::Initializer):
(JSC::LazyProperty::LazyProperty):
(JSC::LazyProperty::get):
(JSC::LazyProperty::getConcurrently):
* runtime/LazyPropertyInlines.h: Added.
(JSC::ElementType>::Initializer::set):
(JSC::ElementType>::initLater):
(JSC::ElementType>::setMayBeNull):
(JSC::ElementType>::set):
(JSC::ElementType>::visit):
(JSC::ElementType>::dump):
(JSC::ElementType>::callFunc):
* runtime/Lookup.cpp:
(JSC::setUpStaticFunctionSlot):
* runtime/Lookup.h:
(JSC::HashTableValue::function):
(JSC::HashTableValue::functionLength):
(JSC::HashTableValue::propertyGetter):
(JSC::HashTableValue::propertyPutter):
(JSC::HashTableValue::accessorGetter):
(JSC::HashTableValue::accessorSetter):
(JSC::HashTableValue::constantInteger):
(JSC::HashTableValue::lexerValue):
(JSC::HashTableValue::lazyCellPropertyOffset):
(JSC::HashTableValue::lazyClassStructureOffset):
(JSC::HashTableValue::lazyPropertyCallback):
(JSC::getStaticPropertySlot):
(JSC::getStaticValueSlot):
(JSC::putEntry):
(JSC::reifyStaticProperty):
* runtime/PropertySlot.h:
* runtime/TypedArrayType.h:

Source/WebCore:

Reviewed by Keith Miller.

No new tests because no change in behavior.

This adapts JSHTMLElementCustom.cpp to the new JSWithScope API. Note that this revealed
that this was using a curious choice of global object, which may not be right. I decided
to do a very literal refactoring that exactly preserves what this code got before, but I
added a FIXME to reconsider this later.

* bindings/js/JSHTMLElementCustom.cpp:
(WebCore::JSHTMLElement::pushEventHandlerScope):

Source/WTF:

Reviewed by Keith Miller.

This WTF change is at the heart of a large JSC change. In JSC I found myself wanting to
do this a lot:

    static void callback(Foo& foo) { ... }

    foo.setCallback(callback);

But that's not very nice to write if many different setCallback() calls are inside of the
same very large function: you'll have to have a lot of static function definitions in
one part of the file, and then a bunch of setCallback() calls in another part. It's hard
to reason about what's going on with such code.

So what if you wrote this instead:

    foo.setCallback([] (Foo& foo) { ... });

Much nicer! There is a standard way to do this: lambdas that are stateless are
convertible to function pointers. This change also offers another approach that is a bit
more general.

These additions to WTF help you do it:

isStatelessLambda<Func>(): tells you if Func is a stateless lambda. This uses is_empty to
test if the lambda is stateless. This turns out to be a stronger property than
convertibility to function pointers. For example, a function pointer is convertible to a
function pointer, but it is definitely stateful: you cannot successfully call it if you
only has its type. On the other hand, a stateless lambda is really stateless in the sense
that you only need its type to call it.

callStatelessLambda<ResultType, Func>(Arguments&&...): calls the given stateless lambda.

JSC uses these to build up some sophisticated lazy-initialization APIs. The use of
statelessness allows JSC to combine a lambda with other logic into a single function
pointer.

* wtf/StdLibExtras.h:
(WTF::isStatelessLambda):
(WTF::callStatelessLambda):

LayoutTests:

Reviewed by Mark Lam.

* js/dom/cross-window-put-math-expected.txt: Added.
* js/dom/cross-window-put-math.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@200430 268f45cc-cd09-0410-ab3c-d52691b4dbfc

48 files changed:
LayoutTests/ChangeLog
LayoutTests/js/dom/cross-window-put-math-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/cross-window-put-math.html [new file with mode: 0644]
Source/JavaScriptCore/API/JSCallbackFunction.cpp
Source/JavaScriptCore/API/ObjCCallbackFunction.h
Source/JavaScriptCore/API/ObjCCallbackFunction.mm
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/create_hash_table
Source/JavaScriptCore/debugger/DebuggerScope.cpp
Source/JavaScriptCore/debugger/DebuggerScope.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
Source/JavaScriptCore/dfg/DFGArrayMode.cpp
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/runtime/ClonedArguments.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/FunctionPrototype.cpp
Source/JavaScriptCore/runtime/InternalFunction.cpp
Source/JavaScriptCore/runtime/InternalFunction.h
Source/JavaScriptCore/runtime/JSBoundFunction.cpp
Source/JavaScriptCore/runtime/JSBoundSlotBaseFunction.cpp
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSNativeStdFunction.cpp
Source/JavaScriptCore/runtime/JSWithScope.cpp
Source/JavaScriptCore/runtime/JSWithScope.h
Source/JavaScriptCore/runtime/LazyClassStructure.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/LazyClassStructure.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/LazyClassStructureInlines.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/LazyProperty.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/LazyPropertyInlines.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/Lookup.cpp
Source/JavaScriptCore/runtime/Lookup.h
Source/JavaScriptCore/runtime/PropertySlot.h
Source/JavaScriptCore/runtime/TypedArrayType.h
Source/WTF/ChangeLog
Source/WTF/wtf/StdLibExtras.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSHTMLElementCustom.cpp

index c0f8788..c22353b 100644 (file)
@@ -1,3 +1,13 @@
+2016-05-04  Filip Pizlo  <fpizlo@apple.com>
+
+        Speed up JSGlobalObject initialization by making some properties lazy
+        https://bugs.webkit.org/show_bug.cgi?id=157045
+
+        Reviewed by Mark Lam.
+
+        * js/dom/cross-window-put-math-expected.txt: Added.
+        * js/dom/cross-window-put-math.html: Added.
+
 2016-05-04  Joseph Pecoraro  <pecoraro@apple.com>
 
         Improve the grammar of some error messages 'a argument list' => 'an argument list'
diff --git a/LayoutTests/js/dom/cross-window-put-math-expected.txt b/LayoutTests/js/dom/cross-window-put-math-expected.txt
new file mode 100644 (file)
index 0000000..b0b92d8
--- /dev/null
@@ -0,0 +1,9 @@
+
+Test storing to a lazy global property.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/cross-window-put-math.html b/LayoutTests/js/dom/cross-window-put-math.html
new file mode 100644 (file)
index 0000000..a35a6b7
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<iframe id="x" src="data:text/html,<p>Hello</p>"></iframe>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description('Test storing to a lazy global property.');
+window.frames[0].Math = window.Math;
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
index 62ea951..a2ecefe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2008, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -58,7 +58,8 @@ void JSCallbackFunction::finishCreation(VM& vm, const String& name)
 
 JSCallbackFunction* JSCallbackFunction::create(VM& vm, JSGlobalObject* globalObject, JSObjectCallAsFunctionCallback callback, const String& name)
 {
-    JSCallbackFunction* function = new (NotNull, allocateCell<JSCallbackFunction>(vm.heap)) JSCallbackFunction(vm, globalObject->callbackFunctionStructure(), callback);
+    Structure* structure = globalObject->callbackFunctionStructure();
+    JSCallbackFunction* function = new (NotNull, allocateCell<JSCallbackFunction>(vm.heap)) JSCallbackFunction(vm, structure, callback);
     function->finishCreation(vm, name);
     return function;
 }
index adb167c..1c0995e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -62,7 +62,7 @@ public:
     ObjCCallbackFunctionImpl* impl() const { return m_impl.get(); }
 
 protected:
-    ObjCCallbackFunction(VM&, JSGlobalObject*, JSObjectCallAsFunctionCallback, JSObjectCallAsConstructorCallback, std::unique_ptr<ObjCCallbackFunctionImpl>);
+    ObjCCallbackFunction(VM&, Structure*, JSObjectCallAsFunctionCallback, JSObjectCallAsConstructorCallback, std::unique_ptr<ObjCCallbackFunctionImpl>);
 
 private:
     static CallType getCallData(JSCell*, CallData&);
index ea98806..b4598e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -498,8 +498,8 @@ static JSObjectRef objCCallbackFunctionCallAsConstructor(JSContextRef callerCont
 
 const JSC::ClassInfo ObjCCallbackFunction::s_info = { "CallbackFunction", &Base::s_info, 0, CREATE_METHOD_TABLE(ObjCCallbackFunction) };
 
-ObjCCallbackFunction::ObjCCallbackFunction(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSObjectCallAsFunctionCallback functionCallback, JSObjectCallAsConstructorCallback constructCallback, std::unique_ptr<ObjCCallbackFunctionImpl> impl)
-    : Base(vm, globalObject->objcCallbackFunctionStructure())
+ObjCCallbackFunction::ObjCCallbackFunction(JSC::VM& vm, JSC::Structure* structure, JSObjectCallAsFunctionCallback functionCallback, JSObjectCallAsConstructorCallback constructCallback, std::unique_ptr<ObjCCallbackFunctionImpl> impl)
+    : Base(vm, structure)
     , m_functionCallback(functionCallback)
     , m_constructCallback(constructCallback)
     , m_impl(WTFMove(impl))
@@ -508,7 +508,8 @@ ObjCCallbackFunction::ObjCCallbackFunction(JSC::VM& vm, JSC::JSGlobalObject* glo
 
 ObjCCallbackFunction* ObjCCallbackFunction::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, const String& name, std::unique_ptr<ObjCCallbackFunctionImpl> impl)
 {
-    ObjCCallbackFunction* function = new (NotNull, allocateCell<ObjCCallbackFunction>(vm.heap)) ObjCCallbackFunction(vm, globalObject, objCCallbackFunctionCallAsFunction, objCCallbackFunctionCallAsConstructor, WTFMove(impl));
+    Structure* structure = globalObject->objcCallbackFunctionStructure();
+    ObjCCallbackFunction* function = new (NotNull, allocateCell<ObjCCallbackFunction>(vm.heap)) ObjCCallbackFunction(vm, structure, objCCallbackFunctionCallAsFunction, objCCallbackFunctionCallAsConstructor, WTFMove(impl));
     function->finishCreation(vm, name);
     return function;
 }
index b43363d..1edbec2 100644 (file)
@@ -740,6 +740,7 @@ set(JavaScriptCore_SOURCES
     runtime/JSWeakSet.cpp
     runtime/JSWithScope.cpp
     runtime/JSWrapperObject.cpp
+    runtime/LazyClassStructure.cpp
     runtime/LiteralParser.cpp
     runtime/Lookup.cpp
     runtime/MapConstructor.cpp
index 94322d3..c9923be 100644 (file)
@@ -1,3 +1,340 @@
+2016-05-04  Filip Pizlo  <fpizlo@apple.com>
+
+        Speed up JSGlobalObject initialization by making some properties lazy
+        https://bugs.webkit.org/show_bug.cgi?id=157045
+
+        Reviewed by Keith Miller.
+        
+        This makes about half of JSGlobalObject's state lazy. There are three categories of
+        state in JSGlobalObject:
+        
+        1) C++ fields in JSGlobalObject.
+        2) JS object properties in JSGlobalObject's JSObject superclass.
+        3) JS variables in JSGlobalObject's JSSegmentedVariableObject superclass.
+        
+        State held in JS variables cannot yet be made lazy. That's why this patch only goes
+        half-way.
+        
+        State in JS object properties can be made lazy if we move it to the static property
+        hashtable. JSGlobalObject already had one of those. This patch makes static property
+        hashtables a lot more powerful, by adding three new kinds of static properties. These
+        new kinds allow us to make almost all of JSGlobalObject's object properties lazy.
+        
+        State in C++ fields can now be made lazy thanks in part to WTF's support for stateless
+        lambdas. You can of course make anything lazy by hand, but there are many C++ fields in
+        JSGlobalObject and we are adding more all the time. We don't want to require that each
+        of these has a getter with an initialization check and a corresponding out-of-line slow
+        path that does the initialization. We want this kind of boilerplate to be handled by
+        some abstractions.
+        
+        The primary abstraction introduced in this patch is LazyProperty<Type>. Currently, this
+        only works where Type is a subclass of JSCell. Such a property holds a pointer to Type.
+        You can use it like you would a WriteBarrier<Type>. It even has set() and get() methods,
+        so it's almost a drop-in replacement.
+        
+        The key to LazyProperty<Type>'s power is that you can do this:
+        
+            class Bar {
+                ...
+                LazyProperty<Foo> m_foo;
+            };
+            ...
+            m_foo.initLater(
+                [] (const LazyProperty<Foo>::Initializer<Bar>& init) {
+                    init.set(Foo::create(init.vm, init.owner));
+                });
+        
+        This initLater() call requires that you pass a stateless lambda (see WTF changelog for
+        the definition). Miraculously, this initLater() call is guaranteed to compile to a store
+        of a pointer constant to m_foo, as in:
+        
+            movabsq 0xBLAH, %rax
+            movq %rax, &m_foo
+        
+        This magical pointer constant points to a callback that was generated by the template
+        instantiation of initLater(). That callback knows to call your stateless lambda, but
+        also does some other bookkeeping: it makes sure that you indeed initialized the property
+        inside the callback and it manages recursive initializations. It's totally legal to call
+        m_foo.get() inside the initLater() callback. If you do that before you call init.set(),
+        m_foo.get() will return null. This is an excellent escape hatch if we ever find
+        ourselves in a dependency cycle. I added this feature because I already had to create a
+        dependency cycle.
+        
+        Note that using LazyProperties from DFG threads is super awkward. It's going to be hard
+        to get this right. The DFG thread cannot initialize those fields, so it has to make sure
+        that it does conservative things. But for some nodes this could mean adding a lot of new
+        logic, like NewTypedArray, which currently is written in such a way that it assumes that
+        we always have the typed array structure. Currently we take a two-fold approach: for
+        typed arrays we don't handle the NewTypedArray intrinsic if the structure isn't
+        initialized, and for everything else we don't make the properties lazy if the DFG needs
+        them. As we optimize this further we might need to teach the DFG to handle more lazy
+        properties. I tried to do this for RegExp but found it to be very confusing. With typed
+        arrays I got lucky.
+        
+        There is also a somewhat more powerful construct called LazyClassStructure. We often
+        need to keep around the structure of some standard JS class, like Date. We also need to
+        make sure that the constructor ends up in the global object's property table. And we
+        often need to keep the original value of the constructor for ourselves. In this case, we
+        want to make sure that the creation of the structure-prototype-constructor constellation
+        is atomic. We don't want code to start looking at the structure if it points to a
+        prototype that doesn't have its "constructor" property set yet, for example.
+        LazyClassStructure solves this by abstracting that whole initialization. You provide the
+        callback that allocates everything, since we are super inconsistent about the way we
+        initialize things, but LazyClassStructure establishes the workflow and helps you not
+        mess up.
+        
+        Finally, the new static hashtable attributes allow for all of this to work with the JS
+        property table:
+        
+        PropertyCallback: if you use this attribute, the second column in the table should be
+        the name of a function to call to initialize this property. This is useful for things
+        like the Math property. The Math object turns out to be very expensive to allocate.
+        Delaying its allocation is super easy with the PropertyCallback attribute.
+        
+        CellProperty: with this attribute the second column should be a C++ field name like
+        JSGlobalObject::m_evalErrorConstructor. The static hashtable will grab the offset of
+        this property, and when it needs to be initialized, Lookup will assume you have a
+        LazyProperty<JSCell> and call its get() method. It will initialize the property to
+        whatever get() returned. Note that it's legal to cast a LazyProperty<Anything> to
+        LazyProperty<JSCell> for the purpose of calling get() because the get() method will just
+        call whatever callback function pointer is encoded in the property and it does not need
+        to know anything about what type that callback will instantiate.
+        
+        ClassStructure: with this attribute the second column should be a C++ field name. The
+        static hashtable will initialize the property by treating the field as a
+        LazyClassStructure and it will call get(). LazyClassStructure completely owns the whole
+        initialization workflow, so Lookup assumes that when LazyClassStructure::get() returns,
+        the property in question will already be set. By convention, we have LazyClassStructure
+        initialize the property with a pointer to the constructor, since that's how all of our
+        classes work: "globalObject.Date" points to the DateConstructor.
+        
+        This is a 2x speed-up in JSGlobalObject initialization time in a microbenchmark that
+        calls our C API. This is a 1% speed-up on SunSpider and JSRegress.
+        
+        Rolling this back in after fixing the function pointer alignment issue. The last version
+        relied on function pointers being aligned to a 4-byte boundary. We cannot rely on this,
+        especially since ARMv7 uses the low bit of function pointers as a tag to indicate the
+        instruction set. This version adds an extra indirection, so that
+        LazyProperty<>::m_pointer points to a pointer that points to the function. A pointer to
+        a pointer is guaranteed to be at least 4-byte aligned.
+
+        * API/JSCallbackFunction.cpp:
+        (JSC::JSCallbackFunction::create):
+        * API/ObjCCallbackFunction.h:
+        (JSC::ObjCCallbackFunction::impl):
+        * API/ObjCCallbackFunction.mm:
+        (JSC::ObjCCallbackFunction::ObjCCallbackFunction):
+        (JSC::ObjCCallbackFunction::create):
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * create_hash_table:
+        * debugger/DebuggerScope.cpp:
+        (JSC::DebuggerScope::create):
+        (JSC::DebuggerScope::DebuggerScope):
+        * debugger/DebuggerScope.h:
+        (JSC::DebuggerScope::jsScope):
+        (JSC::DebuggerScope::create): Deleted.
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGAbstractValue.cpp:
+        (JSC::DFG::AbstractValue::set):
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::ArrayMode::originalArrayStructure):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleTypedArrayConstructor):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileNewTypedArray):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStructureRegistrationPhase.cpp:
+        (JSC::DFG::StructureRegistrationPhase::run):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
+        * runtime/ClonedArguments.cpp:
+        (JSC::ClonedArguments::getOwnPropertySlot):
+        (JSC::ClonedArguments::materializeSpecials):
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/FunctionPrototype.cpp:
+        (JSC::functionProtoFuncToString):
+        * runtime/InternalFunction.cpp:
+        (JSC::InternalFunction::visitChildren):
+        (JSC::InternalFunction::name):
+        (JSC::InternalFunction::calculatedDisplayName):
+        (JSC::InternalFunction::createSubclassStructure):
+        * runtime/InternalFunction.h:
+        * runtime/JSBoundFunction.cpp:
+        (JSC::JSBoundFunction::finishCreation):
+        (JSC::JSBoundFunction::visitChildren):
+        * runtime/JSBoundSlotBaseFunction.cpp:
+        (JSC::JSBoundSlotBaseFunction::create):
+        * runtime/JSFunction.cpp:
+        (JSC::retrieveCallerFunction):
+        (JSC::getThrowTypeErrorGetterSetter):
+        (JSC::JSFunction::callerGetter):
+        (JSC::JSFunction::getOwnPropertySlot):
+        (JSC::JSFunction::defineOwnProperty):
+        * runtime/JSGenericTypedArrayViewConstructorInlines.h:
+        (JSC::constructGenericTypedArrayView):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::createProxyProperty):
+        (JSC::createJSONProperty):
+        (JSC::createMathProperty):
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::stringPrototypeChainIsSane):
+        (JSC::JSGlobalObject::resetPrototype):
+        (JSC::JSGlobalObject::visitChildren):
+        (JSC::JSGlobalObject::toThis):
+        (JSC::JSGlobalObject::getOwnPropertySlot):
+        (JSC::JSGlobalObject::createThrowTypeError): Deleted.
+        (JSC::JSGlobalObject::createThrowTypeErrorArgumentsAndCaller): Deleted.
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::objectConstructor):
+        (JSC::JSGlobalObject::promiseConstructor):
+        (JSC::JSGlobalObject::internalPromiseConstructor):
+        (JSC::JSGlobalObject::evalErrorConstructor):
+        (JSC::JSGlobalObject::rangeErrorConstructor):
+        (JSC::JSGlobalObject::referenceErrorConstructor):
+        (JSC::JSGlobalObject::syntaxErrorConstructor):
+        (JSC::JSGlobalObject::typeErrorConstructor):
+        (JSC::JSGlobalObject::URIErrorConstructor):
+        (JSC::JSGlobalObject::nullGetterFunction):
+        (JSC::JSGlobalObject::nullSetterFunction):
+        (JSC::JSGlobalObject::callFunction):
+        (JSC::JSGlobalObject::applyFunction):
+        (JSC::JSGlobalObject::definePropertyFunction):
+        (JSC::JSGlobalObject::arrayProtoValuesFunction):
+        (JSC::JSGlobalObject::initializePromiseFunction):
+        (JSC::JSGlobalObject::newPromiseCapabilityFunction):
+        (JSC::JSGlobalObject::functionProtoHasInstanceSymbolFunction):
+        (JSC::JSGlobalObject::regExpProtoExecFunction):
+        (JSC::JSGlobalObject::regExpProtoSymbolReplaceFunction):
+        (JSC::JSGlobalObject::regExpProtoGlobalGetter):
+        (JSC::JSGlobalObject::regExpProtoUnicodeGetter):
+        (JSC::JSGlobalObject::throwTypeErrorGetterSetter):
+        (JSC::JSGlobalObject::throwTypeErrorArgumentsAndCallerGetterSetter):
+        (JSC::JSGlobalObject::moduleLoader):
+        (JSC::JSGlobalObject::objectPrototype):
+        (JSC::JSGlobalObject::functionPrototype):
+        (JSC::JSGlobalObject::arrayPrototype):
+        (JSC::JSGlobalObject::booleanPrototype):
+        (JSC::JSGlobalObject::stringPrototype):
+        (JSC::JSGlobalObject::symbolPrototype):
+        (JSC::JSGlobalObject::numberPrototype):
+        (JSC::JSGlobalObject::datePrototype):
+        (JSC::JSGlobalObject::regExpPrototype):
+        (JSC::JSGlobalObject::errorPrototype):
+        (JSC::JSGlobalObject::iteratorPrototype):
+        (JSC::JSGlobalObject::generatorFunctionPrototype):
+        (JSC::JSGlobalObject::generatorPrototype):
+        (JSC::JSGlobalObject::debuggerScopeStructure):
+        (JSC::JSGlobalObject::withScopeStructure):
+        (JSC::JSGlobalObject::strictEvalActivationStructure):
+        (JSC::JSGlobalObject::activationStructure):
+        (JSC::JSGlobalObject::moduleEnvironmentStructure):
+        (JSC::JSGlobalObject::directArgumentsStructure):
+        (JSC::JSGlobalObject::scopedArgumentsStructure):
+        (JSC::JSGlobalObject::clonedArgumentsStructure):
+        (JSC::JSGlobalObject::isOriginalArrayStructure):
+        (JSC::JSGlobalObject::booleanObjectStructure):
+        (JSC::JSGlobalObject::callbackConstructorStructure):
+        (JSC::JSGlobalObject::callbackFunctionStructure):
+        (JSC::JSGlobalObject::callbackObjectStructure):
+        (JSC::JSGlobalObject::propertyNameIteratorStructure):
+        (JSC::JSGlobalObject::objcCallbackFunctionStructure):
+        (JSC::JSGlobalObject::objcWrapperObjectStructure):
+        (JSC::JSGlobalObject::dateStructure):
+        (JSC::JSGlobalObject::nullPrototypeObjectStructure):
+        (JSC::JSGlobalObject::errorStructure):
+        (JSC::JSGlobalObject::calleeStructure):
+        (JSC::JSGlobalObject::functionStructure):
+        (JSC::JSGlobalObject::boundFunctionStructure):
+        (JSC::JSGlobalObject::boundSlotBaseFunctionStructure):
+        (JSC::JSGlobalObject::getterSetterStructure):
+        (JSC::JSGlobalObject::nativeStdFunctionStructure):
+        (JSC::JSGlobalObject::namedFunctionStructure):
+        (JSC::JSGlobalObject::functionNameOffset):
+        (JSC::JSGlobalObject::numberObjectStructure):
+        (JSC::JSGlobalObject::privateNameStructure):
+        (JSC::JSGlobalObject::mapStructure):
+        (JSC::JSGlobalObject::regExpStructure):
+        (JSC::JSGlobalObject::generatorFunctionStructure):
+        (JSC::JSGlobalObject::setStructure):
+        (JSC::JSGlobalObject::stringObjectStructure):
+        (JSC::JSGlobalObject::symbolObjectStructure):
+        (JSC::JSGlobalObject::iteratorResultObjectStructure):
+        (JSC::JSGlobalObject::lazyTypedArrayStructure):
+        (JSC::JSGlobalObject::typedArrayStructure):
+        (JSC::JSGlobalObject::typedArrayStructureConcurrently):
+        (JSC::JSGlobalObject::isOriginalTypedArrayStructure):
+        (JSC::JSGlobalObject::typedArrayConstructor):
+        (JSC::JSGlobalObject::actualPointerFor):
+        (JSC::JSGlobalObject::internalFunctionStructure): Deleted.
+        * runtime/JSNativeStdFunction.cpp:
+        (JSC::JSNativeStdFunction::create):
+        * runtime/JSWithScope.cpp:
+        (JSC::JSWithScope::create):
+        (JSC::JSWithScope::visitChildren):
+        (JSC::JSWithScope::createStructure):
+        (JSC::JSWithScope::JSWithScope):
+        * runtime/JSWithScope.h:
+        (JSC::JSWithScope::object):
+        (JSC::JSWithScope::create): Deleted.
+        (JSC::JSWithScope::createStructure): Deleted.
+        (JSC::JSWithScope::JSWithScope): Deleted.
+        * runtime/LazyClassStructure.cpp: Added.
+        (JSC::LazyClassStructure::Initializer::Initializer):
+        (JSC::LazyClassStructure::Initializer::setPrototype):
+        (JSC::LazyClassStructure::Initializer::setStructure):
+        (JSC::LazyClassStructure::Initializer::setConstructor):
+        (JSC::LazyClassStructure::visit):
+        (JSC::LazyClassStructure::dump):
+        * runtime/LazyClassStructure.h: Added.
+        (JSC::LazyClassStructure::LazyClassStructure):
+        (JSC::LazyClassStructure::get):
+        (JSC::LazyClassStructure::prototype):
+        (JSC::LazyClassStructure::constructor):
+        (JSC::LazyClassStructure::getConcurrently):
+        (JSC::LazyClassStructure::prototypeConcurrently):
+        (JSC::LazyClassStructure::constructorConcurrently):
+        * runtime/LazyClassStructureInlines.h: Added.
+        (JSC::LazyClassStructure::initLater):
+        * runtime/LazyProperty.h: Added.
+        (JSC::LazyProperty::Initializer::Initializer):
+        (JSC::LazyProperty::LazyProperty):
+        (JSC::LazyProperty::get):
+        (JSC::LazyProperty::getConcurrently):
+        * runtime/LazyPropertyInlines.h: Added.
+        (JSC::ElementType>::Initializer::set):
+        (JSC::ElementType>::initLater):
+        (JSC::ElementType>::setMayBeNull):
+        (JSC::ElementType>::set):
+        (JSC::ElementType>::visit):
+        (JSC::ElementType>::dump):
+        (JSC::ElementType>::callFunc):
+        * runtime/Lookup.cpp:
+        (JSC::setUpStaticFunctionSlot):
+        * runtime/Lookup.h:
+        (JSC::HashTableValue::function):
+        (JSC::HashTableValue::functionLength):
+        (JSC::HashTableValue::propertyGetter):
+        (JSC::HashTableValue::propertyPutter):
+        (JSC::HashTableValue::accessorGetter):
+        (JSC::HashTableValue::accessorSetter):
+        (JSC::HashTableValue::constantInteger):
+        (JSC::HashTableValue::lexerValue):
+        (JSC::HashTableValue::lazyCellPropertyOffset):
+        (JSC::HashTableValue::lazyClassStructureOffset):
+        (JSC::HashTableValue::lazyPropertyCallback):
+        (JSC::getStaticPropertySlot):
+        (JSC::getStaticValueSlot):
+        (JSC::putEntry):
+        (JSC::reifyStaticProperty):
+        * runtime/PropertySlot.h:
+        * runtime/TypedArrayType.h:
+
 2016-05-04  Joseph Pecoraro  <pecoraro@apple.com>
 
         Improve the grammar of some error messages 'a argument list' => 'an argument list'
index aa7a72f..5872a38 100644 (file)
                DC17E81A1C9C91E9008A6AB3 /* CCallHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC17E8161C9C802B008A6AB3 /* CCallHelpers.cpp */; };
                DC2143071CA32E55000A8869 /* ICStats.h in Headers */ = {isa = PBXBuildFile; fileRef = DC2143061CA32E52000A8869 /* ICStats.h */; };
                DC2143081CA32E58000A8869 /* ICStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC2143051CA32E52000A8869 /* ICStats.cpp */; };
+               DCF3D5691CD2946D003D5C65 /* LazyClassStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DCF3D5641CD29468003D5C65 /* LazyClassStructure.cpp */; };
+               DCF3D56A1CD29470003D5C65 /* LazyClassStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF3D5651CD29468003D5C65 /* LazyClassStructure.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               DCF3D56B1CD29472003D5C65 /* LazyClassStructureInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF3D5661CD29468003D5C65 /* LazyClassStructureInlines.h */; };
+               DCF3D56C1CD29475003D5C65 /* LazyProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF3D5671CD29468003D5C65 /* LazyProperty.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               DCF3D56D1CD29476003D5C65 /* LazyPropertyInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF3D5681CD29468003D5C65 /* LazyPropertyInlines.h */; };
                DE26E9031CB5DD0500D2BE82 /* BuiltinExecutableCreator.h in Headers */ = {isa = PBXBuildFile; fileRef = DE26E9021CB5DD0500D2BE82 /* BuiltinExecutableCreator.h */; };
                DE26E9071CB5DEFB00D2BE82 /* BuiltinExecutableCreator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE26E9061CB5DD9600D2BE82 /* BuiltinExecutableCreator.cpp */; };
                DE5A0A001BA3AC3E003D4424 /* IntrinsicEmitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */; };
                DC17E8161C9C802B008A6AB3 /* CCallHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCallHelpers.cpp; sourceTree = "<group>"; };
                DC2143051CA32E52000A8869 /* ICStats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ICStats.cpp; sourceTree = "<group>"; };
                DC2143061CA32E52000A8869 /* ICStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ICStats.h; sourceTree = "<group>"; };
+               DCF3D5641CD29468003D5C65 /* LazyClassStructure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LazyClassStructure.cpp; sourceTree = "<group>"; };
+               DCF3D5651CD29468003D5C65 /* LazyClassStructure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LazyClassStructure.h; sourceTree = "<group>"; };
+               DCF3D5661CD29468003D5C65 /* LazyClassStructureInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LazyClassStructureInlines.h; sourceTree = "<group>"; };
+               DCF3D5671CD29468003D5C65 /* LazyProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LazyProperty.h; sourceTree = "<group>"; };
+               DCF3D5681CD29468003D5C65 /* LazyPropertyInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LazyPropertyInlines.h; sourceTree = "<group>"; };
                DE26E9021CB5DD0500D2BE82 /* BuiltinExecutableCreator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltinExecutableCreator.h; sourceTree = "<group>"; };
                DE26E9061CB5DD9600D2BE82 /* BuiltinExecutableCreator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BuiltinExecutableCreator.cpp; sourceTree = "<group>"; };
                DE5A09FF1BA3AC3E003D4424 /* IntrinsicEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntrinsicEmitter.cpp; sourceTree = "<group>"; };
                7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = {
                        isa = PBXGroup;
                        children = (
+                               DCF3D5641CD29468003D5C65 /* LazyClassStructure.cpp */,
+                               DCF3D5651CD29468003D5C65 /* LazyClassStructure.h */,
+                               DCF3D5661CD29468003D5C65 /* LazyClassStructureInlines.h */,
+                               DCF3D5671CD29468003D5C65 /* LazyProperty.h */,
+                               DCF3D5681CD29468003D5C65 /* LazyPropertyInlines.h */,
                                BCF605110E203EF800B9A64D /* ArgList.cpp */,
                                BCF605120E203EF800B9A64D /* ArgList.h */,
                                0FE0500C1AA9091100D33B33 /* ArgumentsMode.h */,
                                A5FD0074189B038C00633231 /* ConsoleTypes.h in Headers */,
                                0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */,
                                E354622B1B6065D100545386 /* ConstructAbility.h in Headers */,
+                               DCF3D56D1CD29476003D5C65 /* LazyPropertyInlines.h in Headers */,
                                BC18C3F60E16F5CD00B34460 /* ConstructData.h in Headers */,
                                A57D23F21891B5B40031C7FA /* ContentSearchUtilities.h in Headers */,
                                52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
                                BC18C4520E16F5CD00B34460 /* LegacyProfiler.h in Headers */,
                                BC18C4310E16F5CD00B34460 /* Lexer.h in Headers */,
                                BC18C52E0E16FCE100B34460 /* Lexer.lut.h in Headers */,
+                               DCF3D56B1CD29472003D5C65 /* LazyClassStructureInlines.h in Headers */,
                                FE187A021BFBE5610038BBCA /* JITMulGenerator.h in Headers */,
                                86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */,
                                0F431738146BAC69007E3890 /* ListableHandler.h in Headers */,
                                86F3EEBD168CDE930077B92A /* ObjCCallbackFunction.h in Headers */,
                                86F3EEBF168CDE930077B92A /* ObjcRuntimeExtras.h in Headers */,
                                14CA958D16AB50FA00938A06 /* ObjectAllocationProfile.h in Headers */,
+                               DCF3D56C1CD29475003D5C65 /* LazyProperty.h in Headers */,
                                BC18C4450E16F5CD00B34460 /* ObjectConstructor.h in Headers */,
                                996B73221BDA08EF00331B84 /* ObjectConstructor.lut.h in Headers */,
                                0FD3E40A1B618B6600C80E1E /* ObjectPropertyCondition.h in Headers */,
                                BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */,
                                93052C350FB792190048FDC3 /* ParserArena.h in Headers */,
                                0FCCAE4516D0CF7400D0C65B /* ParserError.h in Headers */,
+                               DCF3D56A1CD29470003D5C65 /* LazyClassStructure.h in Headers */,
                                A77F1825164192C700640A47 /* ParserModes.h in Headers */,
                                65303D641447B9E100D3F904 /* ParserTokens.h in Headers */,
                                0FF9CE741B9CD6D0004EDCA6 /* PolymorphicAccess.h in Headers */,
                                A54982031891D0B00081E5B8 /* EventLoop.cpp in Sources */,
                                FE1C0FFF1B194FD100B53FCA /* Exception.cpp in Sources */,
                                0F12DE0F1979D5FD0006FF4E /* ExceptionFuzz.cpp in Sources */,
+                               DCF3D5691CD2946D003D5C65 /* LazyClassStructure.cpp in Sources */,
                                1429D8780ED21ACD00B89619 /* ExceptionHelpers.cpp in Sources */,
                                86CA032E1038E8440028A609 /* Executable.cpp in Sources */,
                                0FF054F91AC35B4400E5BE57 /* ExecutableAllocationFuzz.cpp in Sources */,
index dc70e29..1cb2e49 100755 (executable)
@@ -5,7 +5,7 @@
 # (c) 2000-2002 by Harri Porten <porten@kde.org> and
 #                  David Faure <faure@kde.org>
 # Modified (c) 2004 by Nikolas Zimmermann <wildfox@kde.org>
-# Copyright (C) 2007, 2008, 2009, 2015 Apple Inc. All rights reserved.
+# Copyright (C) 2007, 2008, 2009, 2015-2016 Apple Inc. All rights reserved.
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -97,6 +97,15 @@ while (<IN>) {
             my $put = "nullptr";
             $hasSetter = "true";
             push(@values, { "type" => "Accessor", "get" => $get, "put" => $put });
+        } elsif ($att =~ m/CellProperty/) {
+            my $property = $val;
+            push(@values, { "type" => "CellProperty", "property" => $property });
+        } elsif ($att =~ m/ClassStructure/) {
+            my $property = $val;
+            push(@values, { "type" => "ClassStructure", "property" => $property });
+        } elsif ($att =~ m/PropertyCallback/) {
+            my $cback = $val;
+            push(@values, { "type" => "PropertyCallback", "cback" => $cback });
         } elsif (length($att)) {
             my $get = $val;
             my $put = "0";
@@ -298,6 +307,14 @@ sub output() {
         } elsif ($values[$i]{"type"} eq "Lexer") {
             $firstValue = $values[$i]{"value"};
             $secondValue = "0";
+        } elsif ($values[$i]{"type"} eq "CellProperty" || $values[$i]{"type"} eq "ClassStructure") {
+            $values[$i]{"property"} =~ /\A([a-zA-Z0-9_]+)::(.*)\Z/ or die;
+            $firstValue = "OBJECT_OFFSETOF($1, $2)";
+            $secondValue = "0";
+        } elsif ($values[$i]{"type"} eq "PropertyCallback") {
+            $firstCastStr = "static_cast<LazyPropertyCallback>";
+            $firstValue = $values[$i]{"cback"};
+            $secondValue = "0";
         }
 
         my $intrinsic = "NoIntrinsic";
index 0051db7..01d4322 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2009, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2009, 2014, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,8 +36,16 @@ STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DebuggerScope);
 
 const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, 0, CREATE_METHOD_TABLE(DebuggerScope) };
 
-DebuggerScope::DebuggerScope(VM& vm, JSScope* scope)
-    : JSNonFinalObject(vm, scope->globalObject()->debuggerScopeStructure())
+DebuggerScope* DebuggerScope::create(VM& vm, JSScope* scope)
+{
+    Structure* structure = scope->globalObject()->debuggerScopeStructure();
+    DebuggerScope* debuggerScope = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm, structure, scope);
+    debuggerScope->finishCreation(vm);
+    return debuggerScope;
+}
+
+DebuggerScope::DebuggerScope(VM& vm, Structure* structure, JSScope* scope)
+    : JSNonFinalObject(vm, structure)
 {
     ASSERT(scope);
     m_scope.set(vm, this, scope);
index e34f497..e1e8d02 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2009, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2009, 2014, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -38,12 +38,7 @@ public:
     typedef JSNonFinalObject Base;
     static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames;
 
-    static DebuggerScope* create(VM& vm, JSScope* scope)
-    {
-        DebuggerScope* debuggerScope = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm, scope);
-        debuggerScope->finishCreation(vm);
-        return debuggerScope;
-    }
+    JS_EXPORT_PRIVATE static DebuggerScope* create(VM& vm, JSScope* scope);
 
     static void visitChildren(JSCell*, SlotVisitor&);
     static String className(const JSObject*);
@@ -96,8 +91,8 @@ public:
     JSValue caughtValue(ExecState*) const;
 
 private:
-    JS_EXPORT_PRIVATE DebuggerScope(VM&, JSScope*);
-    JS_EXPORT_PRIVATE void finishCreation(VM&);
+    DebuggerScope(VM&, Structure*, JSScope*);
+    void finishCreation(VM&);
 
     JSScope* jsScope() const { return m_scope.get(); }
 
index 8baee33..d79cdab 100644 (file)
@@ -1908,7 +1908,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         }
         forNode(node).set(
             m_graph,
-            m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructure(
+            m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(
                 node->typedArrayType()));
         break;
         
index b95dfa5..f1944b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -77,6 +77,8 @@ void AbstractValue::set(Graph& graph, const FrozenValue& value, StructureClobber
 
 void AbstractValue::set(Graph& graph, Structure* structure)
 {
+    RELEASE_ASSERT(structure);
+    
     m_structure = structure;
     m_arrayModes = asArrayModes(structure->indexingType());
     m_type = speculationFromStructure(structure);
index 162201d..4ea7512 100644 (file)
@@ -323,20 +323,20 @@ Structure* ArrayMode::originalArrayStructure(Graph& graph, const CodeOrigin& cod
             return globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage);
         default:
             CRASH();
-            return 0;
+            return nullptr;
         }
     }
         
     case Array::OriginalNonArray: {
         TypedArrayType type = typedArrayType();
         if (type == NotTypedArray)
-            return 0;
+            return nullptr;
         
-        return globalObject->typedArrayStructure(type);
+        return globalObject->typedArrayStructureConcurrently(type);
     }
         
     default:
-        return 0;
+        return nullptr;
     }
 }
 
index d9f3ce9..0cb250a 100644 (file)
@@ -2604,6 +2604,9 @@ bool ByteCodeParser::handleTypedArrayConstructor(
     
     if (argumentCountIncludingThis != 2)
         return false;
+    
+    if (!function->globalObject()->typedArrayStructureConcurrently(type))
+        return false;
 
     insertChecks();
     set(VirtualRegister(resultOperand),
index 2d4eda3..4a0bd96 100644 (file)
@@ -6855,7 +6855,8 @@ void SpeculativeJIT::compileNewTypedArray(Node* node)
 {
     JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
     TypedArrayType type = node->typedArrayType();
-    Structure* structure = globalObject->typedArrayStructure(type);
+    Structure* structure = globalObject->typedArrayStructureConcurrently(type);
+    RELEASE_ASSERT(structure);
     
     SpeculateInt32Operand size(this, node->child1());
     GPRReg sizeGPR = size.gpr();
index 313b605..de631d4 100644 (file)
@@ -3804,7 +3804,7 @@ void SpeculativeJIT::compile(Node* node)
             JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
             callOperation(
                 operationNewTypedArrayWithOneArgumentForType(node->typedArrayType()),
-                resultGPR, globalObject->typedArrayStructure(node->typedArrayType()),
+                resultGPR, globalObject->typedArrayStructureConcurrently(node->typedArrayType()),
                 argumentTagGPR, argumentPayloadGPR);
             m_jit.exceptionCheck();
             
index 252c205..f53a458 100644 (file)
@@ -3861,7 +3861,7 @@ void SpeculativeJIT::compile(Node* node)
             JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
             callOperation(
                 operationNewTypedArrayWithOneArgumentForType(node->typedArrayType()),
-                resultGPR, globalObject->typedArrayStructure(node->typedArrayType()),
+                resultGPR, globalObject->typedArrayStructureConcurrently(node->typedArrayType()),
                 argumentGPR);
             m_jit.exceptionCheck();
             
index d15935b..51cf489 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -120,7 +120,7 @@ public:
                 }
                     
                 case NewTypedArray:
-                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructure(node->typedArrayType()));
+                    registerStructure(m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(node->typedArrayType()));
                     break;
                     
                 case ToString:
index e9dc811..67bbb00 100644 (file)
@@ -3942,7 +3942,7 @@ private:
         
         switch (m_node->child1().useKind()) {
         case Int32Use: {
-            Structure* structure = globalObject->typedArrayStructure(type);
+            Structure* structure = globalObject->typedArrayStructureConcurrently(type);
 
             LValue size = lowInt32(m_node->child1());
 
@@ -4003,7 +4003,7 @@ private:
 
             LValue result = vmCall(
                 m_out.intPtr, m_out.operation(operationNewTypedArrayWithOneArgumentForType(type)),
-                m_callFrame, weakPointer(globalObject->typedArrayStructure(type)), argument);
+                m_callFrame, weakPointer(globalObject->typedArrayStructureConcurrently(type)), argument);
 
             setJSValue(result);
             return;
index 432406a..829f8e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -158,11 +158,11 @@ bool ClonedArguments::getOwnPropertySlot(JSObject* object, ExecState* exec, Prop
 
         if (isStrictMode) {
             if (ident == vm.propertyNames->callee) {
-                slot.setGetterSlot(thisObject, DontDelete | DontEnum | Accessor, thisObject->globalObject()->throwTypeErrorGetterSetter(vm));
+                slot.setGetterSlot(thisObject, DontDelete | DontEnum | Accessor, thisObject->globalObject()->throwTypeErrorGetterSetter());
                 return true;
             }
             if (ident == vm.propertyNames->caller) {
-                slot.setGetterSlot(thisObject, DontDelete | DontEnum | Accessor, thisObject->globalObject()->throwTypeErrorGetterSetter(vm));
+                slot.setGetterSlot(thisObject, DontDelete | DontEnum | Accessor, thisObject->globalObject()->throwTypeErrorGetterSetter());
                 return true;
             }
 
@@ -238,8 +238,8 @@ void ClonedArguments::materializeSpecials(ExecState* exec)
     bool isStrictMode = executable->isStrictMode();
     
     if (isStrictMode) {
-        putDirectAccessor(exec, vm.propertyNames->callee, globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor);
-        putDirectAccessor(exec, vm.propertyNames->caller, globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor);
+        putDirectAccessor(exec, vm.propertyNames->callee, globalObject()->throwTypeErrorGetterSetter(), DontDelete | DontEnum | Accessor);
+        putDirectAccessor(exec, vm.propertyNames->caller, globalObject()->throwTypeErrorGetterSetter(), DontDelete | DontEnum | Accessor);
     } else
         putDirect(vm, vm.propertyNames->callee, JSValue(m_callee.get()));
 
index 9466809..ad8327a 100644 (file)
@@ -762,7 +762,7 @@ SLOW_PATH_DECL(slow_path_push_with_scope)
 
     int scopeReg = pc[3].u.operand;
     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
-    RETURN(JSWithScope::create(exec, newScope, currentScope));
+    RETURN(JSWithScope::create(vm, exec->lexicalGlobalObject(), newScope, currentScope));
 }
 
 SLOW_PATH_DECL(slow_path_resolve_scope)
index e4416a2..9f5d0fe 100644 (file)
@@ -104,7 +104,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
 
     if (thisValue.inherits(InternalFunction::info())) {
         InternalFunction* function = asInternalFunction(thisValue);
-        return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n    [native code]\n}"));
+        return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n    [native code]\n}"));
     }
 
     if (thisValue.isObject()) {
index a20a563..537b246 100644 (file)
@@ -58,7 +58,7 @@ void InternalFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_originalName);
 }
 
-const String& InternalFunction::name(ExecState*)
+const String& InternalFunction::name()
 {
     const String& name = m_originalName->tryGetValue();
     ASSERT(name); // m_originalName was built from a String, and hence, there is no rope to resolve.
@@ -88,7 +88,7 @@ const String InternalFunction::calculatedDisplayName(ExecState* exec)
     if (!explicitName.isEmpty())
         return explicitName;
     
-    return name(exec);
+    return name();
 }
 
 Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue newTarget, Structure* baseClass)
index c9c0e89..c142ef2 100644 (file)
@@ -40,7 +40,7 @@ public:
 
     JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
 
-    JS_EXPORT_PRIVATE const String& name(ExecState*);
+    JS_EXPORT_PRIVATE const String& name();
     const String displayName(ExecState*);
     const String calculatedDisplayName(ExecState*);
 
index 69d80ec..904c855 100644 (file)
@@ -196,8 +196,8 @@ void JSBoundFunction::finishCreation(VM& vm, NativeExecutable* executable, int l
     Base::finishCreation(vm, executable, length, name);
     ASSERT(inherits(info()));
 
-    putDirectNonIndexAccessor(vm, vm.propertyNames->arguments, globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor);
-    putDirectNonIndexAccessor(vm, vm.propertyNames->caller, globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor);
+    putDirectNonIndexAccessor(vm, vm.propertyNames->arguments, globalObject()->throwTypeErrorGetterSetter(), DontDelete | DontEnum | Accessor);
+    putDirectNonIndexAccessor(vm, vm.propertyNames->caller, globalObject()->throwTypeErrorGetterSetter(), DontDelete | DontEnum | Accessor);
 }
 
 void JSBoundFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
index 16811a8..1f33562 100644 (file)
@@ -64,7 +64,8 @@ JSBoundSlotBaseFunction* JSBoundSlotBaseFunction::create(VM& vm, JSGlobalObject*
 {
     NativeExecutable* executable = vm.getHostFunction(boundSlotBaseFunctionCall, callHostFunctionAsConstructor, name);
 
-    JSBoundSlotBaseFunction* function = new (NotNull, allocateCell<JSBoundSlotBaseFunction>(vm.heap)) JSBoundSlotBaseFunction(vm, globalObject, globalObject->boundSlotBaseFunctionStructure(), type);
+    Structure* structure = globalObject->boundSlotBaseFunctionStructure();
+    JSBoundSlotBaseFunction* function = new (NotNull, allocateCell<JSBoundSlotBaseFunction>(vm.heap)) JSBoundSlotBaseFunction(vm, globalObject, structure, type);
 
     // Can't do this during initialization because getHostFunction might do a GC allocation.
     const char* prefix = (type == Type::Getter) ? "get " : "set ";
index 79e05f3..6ed2456 100644 (file)
@@ -319,11 +319,11 @@ static JSValue retrieveCallerFunction(ExecState* exec, JSFunction* functionObj)
     return functor.result();
 }
 
-static GetterSetter* getThrowTypeErrorGetterSetter(ExecState* exec, JSFunction* function)
+static GetterSetter* getThrowTypeErrorGetterSetter(JSFunction* function)
 {
     return function->jsExecutable()->isClassConstructorFunction() || function->jsExecutable()->parseMode() == SourceParseMode::MethodMode
-        ? function->globalObject()->throwTypeErrorArgumentsAndCallerGetterSetter(exec->vm())
-        : function->globalObject()->throwTypeErrorGetterSetter(exec->vm());
+        ? function->globalObject()->throwTypeErrorArgumentsAndCallerGetterSetter()
+        : function->globalObject()->throwTypeErrorGetterSetter();
 }
 
 EncodedJSValue JSFunction::callerGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
@@ -375,7 +375,7 @@ bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyN
         if (thisObject->jsExecutable()->isStrictMode() || thisObject->jsExecutable()->isClassConstructorFunction()) {
             bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
             if (!result) {
-                GetterSetter* errorGetterSetter = getThrowTypeErrorGetterSetter(exec, thisObject);
+                GetterSetter* errorGetterSetter = getThrowTypeErrorGetterSetter(thisObject);
                 thisObject->putDirectAccessor(exec, propertyName, errorGetterSetter, DontDelete | DontEnum | Accessor);
                 result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
                 ASSERT(result);
@@ -390,7 +390,7 @@ bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyN
         if (thisObject->jsExecutable()->isStrictMode() || thisObject->jsExecutable()->isClassConstructorFunction()) {
             bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
             if (!result) {
-                GetterSetter* errorGetterSetter = getThrowTypeErrorGetterSetter(exec, thisObject);
+                GetterSetter* errorGetterSetter = getThrowTypeErrorGetterSetter(thisObject);
                 thisObject->putDirectAccessor(exec, propertyName, errorGetterSetter, DontDelete | DontEnum | Accessor);
                 result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
                 ASSERT(result);
@@ -499,7 +499,7 @@ bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNa
         if (thisObject->jsExecutable()->isStrictMode()) {
             PropertySlot slot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
             if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
-                thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
+                thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(), DontDelete | DontEnum | Accessor);
             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
         }
         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), retrieveArguments(exec, thisObject));
@@ -507,7 +507,7 @@ bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNa
         if (thisObject->jsExecutable()->isStrictMode()) {
             PropertySlot slot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
             if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
-                thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
+                thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(), DontDelete | DontEnum | Accessor);
             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
         }
         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), retrieveCallerFunction(exec, thisObject));
index a2b4cb7..f3c7c68 100644 (file)
@@ -221,7 +221,9 @@ EncodedJSValue JSC_HOST_CALL constructGenericTypedArrayView(ExecState*);
 template<typename ViewClass>
 EncodedJSValue JSC_HOST_CALL constructGenericTypedArrayView(ExecState* exec)
 {
-    Structure* structure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), asInternalFunction(exec->callee())->globalObject()->typedArrayStructure(ViewClass::TypedArrayStorageType));
+    InternalFunction* function = asInternalFunction(exec->callee());
+    Structure* parentStructure = function->globalObject()->typedArrayStructure(ViewClass::TypedArrayStorageType);
+    Structure* structure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), parentStructure);
     if (exec->hadException())
         return JSValue::encode(JSValue());
 
index a7dce89..eba22f8 100644 (file)
 #include "JSWeakMap.h"
 #include "JSWeakSet.h"
 #include "JSWithScope.h"
+#include "LazyClassStructureInlines.h"
+#include "LazyPropertyInlines.h"
 #include "LegacyProfiler.h"
 #include "Lookup.h"
 #include "MapConstructor.h"
 #include "JSReplayInputs.h"
 #endif
 
+namespace JSC {
+
+static JSValue createProxyProperty(VM& vm, JSObject* object)
+{
+    JSGlobalObject* global = jsCast<JSGlobalObject*>(object);
+    return ProxyConstructor::create(vm, ProxyConstructor::createStructure(vm, global, global->functionPrototype()));
+}
+
+static JSValue createJSONProperty(VM& vm, JSObject* object)
+{
+    JSGlobalObject* global = jsCast<JSGlobalObject*>(object);
+    return JSONObject::create(vm, JSONObject::createStructure(vm, global, global->objectPrototype()));
+}
+
+static JSValue createMathProperty(VM& vm, JSObject* object)
+{
+    JSGlobalObject* global = jsCast<JSGlobalObject*>(object);
+    return MathObject::create(vm, global, MathObject::createStructure(vm, global, global->objectPrototype()));
+}
+
+} // namespace JSC
+
 #include "JSGlobalObject.lut.h"
 
 namespace JSC {
@@ -182,15 +206,39 @@ const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &all
 
 /* Source for JSGlobalObject.lut.h
 @begin globalObjectTable
-  parseFloat            globalFuncParseFloat            DontEnum|Function 1
-  isNaN                 globalFuncIsNaN                 DontEnum|Function 1
-  isFinite              globalFuncIsFinite              DontEnum|Function 1
-  escape                globalFuncEscape                DontEnum|Function 1
-  unescape              globalFuncUnescape              DontEnum|Function 1
-  decodeURI             globalFuncDecodeURI             DontEnum|Function 1
-  decodeURIComponent    globalFuncDecodeURIComponent    DontEnum|Function 1
-  encodeURI             globalFuncEncodeURI             DontEnum|Function 1
-  encodeURIComponent    globalFuncEncodeURIComponent    DontEnum|Function 1
+  parseFloat            globalFuncParseFloat                         DontEnum|Function 1
+  isNaN                 globalFuncIsNaN                              DontEnum|Function 1
+  isFinite              globalFuncIsFinite                           DontEnum|Function 1
+  escape                globalFuncEscape                             DontEnum|Function 1
+  unescape              globalFuncUnescape                           DontEnum|Function 1
+  decodeURI             globalFuncDecodeURI                          DontEnum|Function 1
+  decodeURIComponent    globalFuncDecodeURIComponent                 DontEnum|Function 1
+  encodeURI             globalFuncEncodeURI                          DontEnum|Function 1
+  encodeURIComponent    globalFuncEncodeURIComponent                 DontEnum|Function 1
+  EvalError             JSGlobalObject::m_evalErrorConstructor       DontEnum|CellProperty
+  ReferenceError        JSGlobalObject::m_referenceErrorConstructor  DontEnum|CellProperty
+  SyntaxError           JSGlobalObject::m_syntaxErrorConstructor     DontEnum|CellProperty
+  URIError              JSGlobalObject::m_URIErrorConstructor        DontEnum|CellProperty
+  Proxy                 createProxyProperty                          DontEnum|PropertyCallback
+  JSON                  createJSONProperty                           DontEnum|PropertyCallback
+  Math                  createMathProperty                           DontEnum|PropertyCallback
+  Int8Array             JSGlobalObject::m_typedArrayInt8             DontEnum|ClassStructure
+  Int16Array            JSGlobalObject::m_typedArrayInt16            DontEnum|ClassStructure
+  Int32Array            JSGlobalObject::m_typedArrayInt32            DontEnum|ClassStructure
+  Uint8Array            JSGlobalObject::m_typedArrayUint8            DontEnum|ClassStructure
+  Uint8ClampedArray     JSGlobalObject::m_typedArrayUint8Clamped     DontEnum|ClassStructure
+  Uint16Array           JSGlobalObject::m_typedArrayUint16           DontEnum|ClassStructure
+  Uint32Array           JSGlobalObject::m_typedArrayUint32           DontEnum|ClassStructure
+  Float32Array          JSGlobalObject::m_typedArrayFloat32          DontEnum|ClassStructure
+  Float64Array          JSGlobalObject::m_typedArrayFloat64          DontEnum|ClassStructure
+  DataView              JSGlobalObject::m_typedArrayDataView         DontEnum|ClassStructure
+  Set                   JSGlobalObject::m_setStructure               DontEnum|ClassStructure
+  Map                   JSGlobalObject::m_mapStructure               DontEnum|ClassStructure
+  Date                  JSGlobalObject::m_dateStructure              DontEnum|ClassStructure
+  Boolean               JSGlobalObject::m_booleanObjectStructure     DontEnum|ClassStructure
+  Number                JSGlobalObject::m_numberObjectStructure      DontEnum|ClassStructure
+  WeakMap               JSGlobalObject::m_weakMapStructure           DontEnum|ClassStructure
+  WeakSet               JSGlobalObject::m_weakSetStructure           DontEnum|ClassStructure
 @end
 */
 
@@ -291,22 +339,55 @@ void JSGlobalObject::init(VM& vm)
     exec->setCallee(m_globalCallee.get());
 
     m_functionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
-    m_boundSlotBaseFunctionStructure.set(vm, this, JSBoundSlotBaseFunction::createStructure(vm, this, m_functionPrototype.get()));
-    m_boundFunctionStructure.set(vm, this, JSBoundFunction::createStructure(vm, this, m_functionPrototype.get()));
+    m_boundSlotBaseFunctionStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(JSBoundSlotBaseFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
+        });
+    m_boundFunctionStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(JSBoundFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
+        });
     m_getterSetterStructure.set(vm, this, GetterSetter::createStructure(vm, this, jsNull()));
-    m_nativeStdFunctionStructure.set(vm, this, JSNativeStdFunction::createStructure(vm, this, m_functionPrototype.get()));
-    m_namedFunctionStructure.set(vm, this, Structure::addPropertyTransition(vm, m_functionStructure.get(), vm.propertyNames->name, DontDelete | ReadOnly | DontEnum, m_functionNameOffset));
-    m_internalFunctionStructure.set(vm, this, InternalFunction::createStructure(vm, this, m_functionPrototype.get()));
+    m_nativeStdFunctionStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(JSNativeStdFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
+        });
+    m_namedFunctionStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(Structure::addPropertyTransition(init.vm, init.owner->m_functionStructure.get(), init.vm.propertyNames->name, DontDelete | ReadOnly | DontEnum, init.owner->m_functionNameOffset));
+        });
     JSFunction* callFunction = 0;
     JSFunction* applyFunction = 0;
     JSFunction* hasInstanceSymbolFunction = 0;
     m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction, &hasInstanceSymbolFunction);
     m_callFunction.set(vm, this, callFunction);
     m_applyFunction.set(vm, this, applyFunction);
-    m_arrayProtoValuesFunction.set(vm, this, JSFunction::createBuiltinFunction(vm, arrayPrototypeValuesCodeGenerator(vm), this));
-    m_initializePromiseFunction.set(vm, this, JSFunction::createBuiltinFunction(vm, promiseOperationsInitializePromiseCodeGenerator(vm), this));
+    m_arrayProtoValuesFunction.initLater(
+        [] (const Initializer<JSFunction>& init) {
+            init.set(JSFunction::createBuiltinFunction(init.vm, arrayPrototypeValuesCodeGenerator(init.vm), init.owner));
+        });
+    m_initializePromiseFunction.initLater(
+        [] (const Initializer<JSFunction>& init) {
+            init.set(JSFunction::createBuiltinFunction(init.vm, promiseOperationsInitializePromiseCodeGenerator(init.vm), init.owner));
+        });
     m_newPromiseCapabilityFunction.set(vm, this, JSFunction::createBuiltinFunction(vm, promiseOperationsNewPromiseCapabilityCodeGenerator(vm), this));
     m_functionProtoHasInstanceSymbolFunction.set(vm, this, hasInstanceSymbolFunction);
+    m_throwTypeErrorGetterSetter.initLater(
+        [] (const Initializer<GetterSetter>& init) {
+            JSFunction* thrower = JSFunction::create(init.vm, init.owner, 0, String(), globalFuncThrowTypeError);
+            GetterSetter* getterSetter = GetterSetter::create(init.vm, init.owner);
+            getterSetter->setGetter(init.vm, init.owner, thrower);
+            getterSetter->setSetter(init.vm, init.owner, thrower);
+            init.set(getterSetter);
+        });
+    m_throwTypeErrorArgumentsAndCallerGetterSetter.initLater(
+        [] (const Initializer<GetterSetter>& init) {
+            JSFunction* thrower = JSFunction::create(init.vm, init.owner, 0, String(), globalFuncThrowTypeErrorArgumentsAndCaller);
+            GetterSetter* getterSetter = GetterSetter::create(init.vm, init.owner);
+            getterSetter->setGetter(init.vm, init.owner, thrower);
+            getterSetter->setSetter(init.vm, init.owner, thrower);
+            init.set(getterSetter);
+        });
     m_nullGetterFunction.set(vm, this, NullGetterFunction::create(vm, NullGetterFunction::createStructure(vm, this, m_functionPrototype.get())));
     m_nullSetterFunction.set(vm, this, NullSetterFunction::create(vm, NullSetterFunction::createStructure(vm, this, m_functionPrototype.get())));
     m_objectPrototype.set(vm, this, ObjectPrototype::create(vm, this, ObjectPrototype::createStructure(vm, this, jsNull())));
@@ -317,48 +398,87 @@ void JSGlobalObject::init(VM& vm)
     m_functionPrototype->structure()->setPrototypeWithoutTransition(vm, m_objectPrototype.get());
     m_objectStructureForObjectConstructor.set(vm, this, vm.prototypeMap.emptyObjectStructureForPrototype(m_objectPrototype.get(), JSFinalObject::defaultInlineCapacity()));
 
-    JSTypedArrayViewPrototype* typedArrayProto = JSTypedArrayViewPrototype::create(vm, this, JSTypedArrayViewPrototype::createStructure(vm, this, m_objectPrototype.get()));
-
-    m_typedArrays[toIndex(TypeInt8)].prototype.set(vm, this, JSInt8ArrayPrototype::create(vm, this, JSInt8ArrayPrototype::createStructure(vm, this, typedArrayProto)));
-    m_typedArrays[toIndex(TypeInt16)].prototype.set(vm, this, JSInt16ArrayPrototype::create(vm, this, JSInt16ArrayPrototype::createStructure(vm, this, typedArrayProto)));
-    m_typedArrays[toIndex(TypeInt32)].prototype.set(vm, this, JSInt32ArrayPrototype::create(vm, this, JSInt32ArrayPrototype::createStructure(vm, this, typedArrayProto)));
-    m_typedArrays[toIndex(TypeUint8)].prototype.set(vm, this, JSUint8ArrayPrototype::create(vm, this, JSUint8ArrayPrototype::createStructure(vm, this, typedArrayProto)));
-    m_typedArrays[toIndex(TypeUint8Clamped)].prototype.set(vm, this, JSUint8ClampedArrayPrototype::create(vm, this, JSUint8ClampedArrayPrototype::createStructure(vm, this, typedArrayProto)));
-    m_typedArrays[toIndex(TypeUint16)].prototype.set(vm, this, JSUint16ArrayPrototype::create(vm, this, JSUint16ArrayPrototype::createStructure(vm, this, typedArrayProto)));
-    m_typedArrays[toIndex(TypeUint32)].prototype.set(vm, this, JSUint32ArrayPrototype::create(vm, this, JSUint32ArrayPrototype::createStructure(vm, this, typedArrayProto)));
-    m_typedArrays[toIndex(TypeFloat32)].prototype.set(vm, this, JSFloat32ArrayPrototype::create(vm, this, JSFloat32ArrayPrototype::createStructure(vm, this, typedArrayProto)));
-    m_typedArrays[toIndex(TypeFloat64)].prototype.set(vm, this, JSFloat64ArrayPrototype::create(vm, this, JSFloat64ArrayPrototype::createStructure(vm, this, typedArrayProto)));
-    m_typedArrays[toIndex(TypeDataView)].prototype.set(vm, this, JSDataViewPrototype::create(vm, JSDataViewPrototype::createStructure(vm, this, m_objectPrototype.get())));
+    m_speciesGetterSetter.set(vm, this, GetterSetter::create(vm, this));
+    m_speciesGetterSetter->setGetter(vm, this, JSFunction::createBuiltinFunction(vm, globalObjectSpeciesGetterCodeGenerator(vm), this, "get [Symbol.species]"));
+
+    m_typedArrayProto.initLater(
+        [] (const Initializer<JSTypedArrayViewPrototype>& init) {
+            init.set(JSTypedArrayViewPrototype::create(init.vm, init.owner, JSTypedArrayViewPrototype::createStructure(init.vm, init.owner, init.owner->m_objectPrototype.get())));
+            
+            // Make sure that the constructor gets initialized, too.
+            init.owner->m_typedArraySuperConstructor.get(init.owner);
+        });
+    m_typedArraySuperConstructor.initLater(
+        [] (const Initializer<JSTypedArrayViewConstructor>& init) {
+            JSTypedArrayViewPrototype* prototype = init.owner->m_typedArrayProto.get(init.owner);
+            JSTypedArrayViewConstructor* constructor = JSTypedArrayViewConstructor::create(init.vm, init.owner, JSTypedArrayViewConstructor::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()), prototype, init.owner->m_speciesGetterSetter.get());
+            prototype->putDirectWithoutTransition(init.vm, init.vm.propertyNames->constructor, constructor, DontEnum);
+            init.set(constructor);
+        });
+    
+#define INIT_TYPED_ARRAY_LATER(type) \
+    m_typedArray ## type.initLater( \
+        [] (LazyClassStructure::Initializer& init) { \
+            init.setPrototype(JS ## type ## ArrayPrototype::create(init.vm, init.global, JS ## type ## ArrayPrototype::createStructure(init.vm, init.global, init.global->m_typedArrayProto.get(init.global)))); \
+            init.setStructure(JS ## type ## Array::createStructure(init.vm, init.global, init.prototype)); \
+            init.setConstructor(JS ## type ## ArrayConstructor::create(init.vm, init.global, JS ## type ## ArrayConstructor::createStructure(init.vm, init.global, init.global->m_typedArraySuperConstructor.get(init.global)), init.prototype, ASCIILiteral(#type "Array"), typedArrayConstructorAllocate ## type ## ArrayCodeGenerator(init.vm))); \
+            init.global->putDirectWithoutTransition(init.vm, init.vm.propertyNames->type ## ArrayPrivateName, init.constructor, DontEnum); \
+        });
+    FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(INIT_TYPED_ARRAY_LATER)
+#undef INIT_TYPED_ARRAY_LATER
     
-    m_typedArrays[toIndex(TypeInt8)].structure.set(vm, this, JSInt8Array::createStructure(vm, this, m_typedArrays[toIndex(TypeInt8)].prototype.get()));
-    m_typedArrays[toIndex(TypeInt16)].structure.set(vm, this, JSInt16Array::createStructure(vm, this, m_typedArrays[toIndex(TypeInt16)].prototype.get()));
-    m_typedArrays[toIndex(TypeInt32)].structure.set(vm, this, JSInt32Array::createStructure(vm, this, m_typedArrays[toIndex(TypeInt32)].prototype.get()));
-    m_typedArrays[toIndex(TypeUint8)].structure.set(vm, this, JSUint8Array::createStructure(vm, this, m_typedArrays[toIndex(TypeUint8)].prototype.get()));
-    m_typedArrays[toIndex(TypeUint8Clamped)].structure.set(vm, this, JSUint8ClampedArray::createStructure(vm, this, m_typedArrays[toIndex(TypeUint8Clamped)].prototype.get()));
-    m_typedArrays[toIndex(TypeUint16)].structure.set(vm, this, JSUint16Array::createStructure(vm, this, m_typedArrays[toIndex(TypeUint16)].prototype.get()));
-    m_typedArrays[toIndex(TypeUint32)].structure.set(vm, this, JSUint32Array::createStructure(vm, this, m_typedArrays[toIndex(TypeUint32)].prototype.get()));
-    m_typedArrays[toIndex(TypeFloat32)].structure.set(vm, this, JSFloat32Array::createStructure(vm, this, m_typedArrays[toIndex(TypeFloat32)].prototype.get()));
-    m_typedArrays[toIndex(TypeFloat64)].structure.set(vm, this, JSFloat64Array::createStructure(vm, this, m_typedArrays[toIndex(TypeFloat64)].prototype.get()));
-    m_typedArrays[toIndex(TypeDataView)].structure.set(vm, this, JSDataView::createStructure(vm, this, m_typedArrays[toIndex(TypeDataView)].prototype.get()));
+    m_typedArrayDataView.initLater(
+        [] (LazyClassStructure::Initializer& init) {
+            init.setPrototype(JSDataViewPrototype::create(init.vm, JSDataViewPrototype::createStructure(init.vm, init.global, init.global->m_objectPrototype.get())));
+            init.setStructure(JSDataView::createStructure(init.vm, init.global, init.prototype));
+            init.setConstructor(JSDataViewConstructor::create(init.vm, init.global, JSDataViewConstructor::createStructure(init.vm, init.global, init.global->m_functionPrototype.get()), init.prototype, ASCIILiteral("DataView"), nullptr));
+        });
     
     m_lexicalEnvironmentStructure.set(vm, this, JSLexicalEnvironment::createStructure(vm, this));
-    m_moduleEnvironmentStructure.set(vm, this, JSModuleEnvironment::createStructure(vm, this));
+    m_moduleEnvironmentStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(JSModuleEnvironment::createStructure(init.vm, init.owner));
+        });
     m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull()));
-    m_debuggerScopeStructure.set(m_vm, this, DebuggerScope::createStructure(m_vm, this));
-    m_withScopeStructure.set(vm, this, JSWithScope::createStructure(vm, this, jsNull()));
+    m_debuggerScopeStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(DebuggerScope::createStructure(init.vm, init.owner));
+        });
+    m_withScopeStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(JSWithScope::createStructure(init.vm, init.owner, jsNull()));
+        });
     
-    m_nullPrototypeObjectStructure.set(vm, this, JSFinalObject::createStructure(vm, this, jsNull(), JSFinalObject::defaultInlineCapacity()));
+    m_nullPrototypeObjectStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(JSFinalObject::createStructure(init.vm, init.owner, jsNull(), JSFinalObject::defaultInlineCapacity()));
+        });
     
-    m_callbackFunctionStructure.set(vm, this, JSCallbackFunction::createStructure(vm, this, m_functionPrototype.get()));
+    m_callbackFunctionStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(JSCallbackFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
+        });
     m_directArgumentsStructure.set(vm, this, DirectArguments::createStructure(vm, this, m_objectPrototype.get()));
     m_scopedArgumentsStructure.set(vm, this, ScopedArguments::createStructure(vm, this, m_objectPrototype.get()));
     m_clonedArgumentsStructure.set(vm, this, ClonedArguments::createStructure(vm, this, m_objectPrototype.get()));
-    m_callbackConstructorStructure.set(vm, this, JSCallbackConstructor::createStructure(vm, this, m_objectPrototype.get()));
-    m_callbackObjectStructure.set(vm, this, JSCallbackObject<JSDestructibleObject>::createStructure(vm, this, m_objectPrototype.get()));
+    m_callbackConstructorStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(JSCallbackConstructor::createStructure(init.vm, init.owner, init.owner->m_objectPrototype.get()));
+        });
+    m_callbackObjectStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(JSCallbackObject<JSDestructibleObject>::createStructure(init.vm, init.owner, init.owner->m_objectPrototype.get()));
+        });
 
 #if JSC_OBJC_API_ENABLED
-    m_objcCallbackFunctionStructure.set(vm, this, ObjCCallbackFunction::createStructure(vm, this, m_functionPrototype.get()));
-    m_objcWrapperObjectStructure.set(vm, this, JSCallbackObject<JSAPIWrapperObject>::createStructure(vm, this, m_objectPrototype.get()));
+    m_objcCallbackFunctionStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(ObjCCallbackFunction::createStructure(init.vm, init.owner, init.owner->m_functionPrototype.get()));
+        });
+    m_objcWrapperObjectStructure.initLater(
+        [] (const Initializer<Structure>& init) {
+            init.set(JSCallbackObject<JSAPIWrapperObject>::createStructure(init.vm, init.owner, init.owner->m_objectPrototype.get()));
+        });
 #endif
     
     m_arrayPrototype.set(vm, this, ArrayPrototype::create(vm, this, ArrayPrototype::createStructure(vm, this, m_objectPrototype.get())));
@@ -402,23 +522,34 @@ m_ ## properName ## Structure.set(vm, this, instanceType::createStructure(vm, th
     
 #undef CREATE_PROTOTYPE_FOR_SIMPLE_TYPE
 
+#define CREATE_PROTOTYPE_FOR_LAZY_TYPE(capitalName, lowerName, properName, instanceType, jsName) \
+    m_ ## properName ## Structure.initLater(\
+        [] (LazyClassStructure::Initializer& init) { \
+            init.setPrototype(capitalName##Prototype::create(init.vm, init.global, capitalName##Prototype::createStructure(init.vm, init.global, init.global->m_objectPrototype.get()))); \
+            init.setStructure(instanceType::createStructure(init.vm, init.global, init.prototype)); \
+            init.setConstructor(capitalName ## Constructor::create(init.vm, capitalName ## Constructor::createStructure(init.vm, init.global, init.global->m_functionPrototype.get()), jsCast<capitalName ## Prototype*>(init.prototype), init.global->m_speciesGetterSetter.get())); \
+        });
+    
+    FOR_EACH_LAZY_BUILTIN_TYPE(CREATE_PROTOTYPE_FOR_LAZY_TYPE)
+    
+#undef CREATE_PROTOTYPE_FOR_LAZY_TYPE
+    
     m_iteratorPrototype.set(vm, this, IteratorPrototype::create(vm, this, IteratorPrototype::createStructure(vm, this, m_objectPrototype.get())));
 
 #define CREATE_PROTOTYPE_FOR_DERIVED_ITERATOR_TYPE(capitalName, lowerName, properName, instanceType, jsName) \
-m_ ## lowerName ## Prototype.set(vm, this, capitalName##Prototype::create(vm, this, capitalName##Prototype::createStructure(vm, this, m_iteratorPrototype.get()))); \
-m_ ## properName ## Structure.set(vm, this, instanceType::createStructure(vm, this, m_ ## lowerName ## Prototype.get()));
-    
+    m_ ## lowerName ## Structure.initLater( \
+        [] (const Initializer<Structure>& init) { \
+            JSObject* prototype = capitalName ## Prototype::create(init.vm, init.owner, capitalName ## Prototype::createStructure(init.vm, init.owner, init.owner->m_iteratorPrototype.get())); \
+            init.set(instanceType::createStructure(init.vm, init.owner, prototype)); \
+        });
     FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(CREATE_PROTOTYPE_FOR_DERIVED_ITERATOR_TYPE)
+#undef CREATE_PROTOTYPE_FOR_DERIVED_ITERATOR_TYPE
+
     m_propertyNameIteratorStructure.set(vm, this, JSPropertyNameIterator::createStructure(vm, this, m_iteratorPrototype.get()));
     m_generatorPrototype.set(vm, this, GeneratorPrototype::create(vm, this, GeneratorPrototype::createStructure(vm, this, m_iteratorPrototype.get())));
     
-#undef CREATE_PROTOTYPE_FOR_DERIVED_ITERATOR_TYPE
-
     // Constructors
 
-    GetterSetter* speciesGetterSetter = GetterSetter::create(vm, this);
-    speciesGetterSetter->setGetter(vm, this, JSFunction::createBuiltinFunction(vm, globalObjectSpeciesGetterCodeGenerator(vm), this, "get [Symbol.species]"));
-
     ObjectConstructor* objectConstructor = ObjectConstructor::create(vm, this, ObjectConstructor::createStructure(vm, this, m_functionPrototype.get()), m_objectPrototype.get());
     m_objectConstructor.set(vm, this, objectConstructor);
 
@@ -426,30 +557,42 @@ m_ ## properName ## Structure.set(vm, this, instanceType::createStructure(vm, th
     m_definePropertyFunction.set(vm, this, definePropertyFunction);
 
     JSCell* functionConstructor = FunctionConstructor::create(vm, FunctionConstructor::createStructure(vm, this, m_functionPrototype.get()), m_functionPrototype.get());
-    JSObject* arrayConstructor = ArrayConstructor::create(vm, this, ArrayConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayPrototype.get(), speciesGetterSetter);
+    JSObject* arrayConstructor = ArrayConstructor::create(vm, this, ArrayConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayPrototype.get(), m_speciesGetterSetter.get());
     
-    m_regExpConstructor.set(vm, this, RegExpConstructor::create(vm, RegExpConstructor::createStructure(vm, this, m_functionPrototype.get()), m_regExpPrototype.get(), speciesGetterSetter));
+    m_regExpConstructor.set(vm, this, RegExpConstructor::create(vm, RegExpConstructor::createStructure(vm, this, m_functionPrototype.get()), m_regExpPrototype.get(), m_speciesGetterSetter.get()));
     
 #define CREATE_CONSTRUCTOR_FOR_SIMPLE_TYPE(capitalName, lowerName, properName, instanceType, jsName) \
-capitalName ## Constructor* lowerName ## Constructor = capitalName ## Constructor::create(vm, capitalName ## Constructor::createStructure(vm, this, m_functionPrototype.get()), m_ ## lowerName ## Prototype.get(), speciesGetterSetter); \
+capitalName ## Constructor* lowerName ## Constructor = capitalName ## Constructor::create(vm, capitalName ## Constructor::createStructure(vm, this, m_functionPrototype.get()), m_ ## lowerName ## Prototype.get(), m_speciesGetterSetter.get()); \
 m_ ## lowerName ## Prototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, lowerName ## Constructor, DontEnum); \
 
     FOR_EACH_SIMPLE_BUILTIN_TYPE(CREATE_CONSTRUCTOR_FOR_SIMPLE_TYPE)
     
 #undef CREATE_CONSTRUCTOR_FOR_SIMPLE_TYPE
-    
+
     m_errorConstructor.set(vm, this, errorConstructor);
     m_promiseConstructor.set(vm, this, promiseConstructor);
     m_internalPromiseConstructor.set(vm, this, internalPromiseConstructor);
     
-    Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(vm, this, m_errorPrototype.get());
-    Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(vm, this, m_functionPrototype.get());
-    m_evalErrorConstructor.set(vm, this, NativeErrorConstructor::create(vm, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("EvalError")));
-    m_rangeErrorConstructor.set(vm, this, NativeErrorConstructor::create(vm, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("RangeError")));
-    m_referenceErrorConstructor.set(vm, this, NativeErrorConstructor::create(vm, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("ReferenceError")));
-    m_syntaxErrorConstructor.set(vm, this, NativeErrorConstructor::create(vm, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("SyntaxError")));
-    m_typeErrorConstructor.set(vm, this, NativeErrorConstructor::create(vm, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("TypeError")));
-    m_URIErrorConstructor.set(vm, this, NativeErrorConstructor::create(vm, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("URIError")));
+    m_nativeErrorPrototypeStructure.set(vm, this, NativeErrorPrototype::createStructure(vm, this, m_errorPrototype.get()));
+    m_nativeErrorStructure.set(vm, this, NativeErrorConstructor::createStructure(vm, this, m_functionPrototype.get()));
+    m_evalErrorConstructor.initLater(
+        [] (const Initializer<NativeErrorConstructor>& init) {
+            init.set(NativeErrorConstructor::create(init.vm, init.owner, init.owner->m_nativeErrorStructure.get(), init.owner->m_nativeErrorPrototypeStructure.get(), ASCIILiteral("EvalError")));
+        });
+    m_rangeErrorConstructor.set(vm, this, NativeErrorConstructor::create(vm, this, m_nativeErrorStructure.get(), m_nativeErrorPrototypeStructure.get(), ASCIILiteral("RangeError")));
+    m_referenceErrorConstructor.initLater(
+        [] (const Initializer<NativeErrorConstructor>& init) {
+            init.set(NativeErrorConstructor::create(init.vm, init.owner, init.owner->m_nativeErrorStructure.get(), init.owner->m_nativeErrorPrototypeStructure.get(), ASCIILiteral("ReferenceError")));
+        });
+    m_syntaxErrorConstructor.initLater(
+        [] (const Initializer<NativeErrorConstructor>& init) {
+            init.set(NativeErrorConstructor::create(init.vm, init.owner, init.owner->m_nativeErrorStructure.get(), init.owner->m_nativeErrorPrototypeStructure.get(), ASCIILiteral("SyntaxError")));
+        });
+    m_typeErrorConstructor.set(vm, this, NativeErrorConstructor::create(vm, this, m_nativeErrorStructure.get(), m_nativeErrorPrototypeStructure.get(), ASCIILiteral("TypeError")));
+    m_URIErrorConstructor.initLater(
+        [] (const Initializer<NativeErrorConstructor>& init) {
+            init.set(NativeErrorConstructor::create(init.vm, init.owner, init.owner->m_nativeErrorStructure.get(), init.owner->m_nativeErrorPrototypeStructure.get(), ASCIILiteral("URIError")));
+        });
 
     m_generatorFunctionPrototype.set(vm, this, GeneratorFunctionPrototype::create(vm, GeneratorFunctionPrototype::createStructure(vm, this, m_functionPrototype.get())));
     GeneratorFunctionConstructor* generatorFunctionConstructor = GeneratorFunctionConstructor::create(vm, GeneratorFunctionConstructor::createStructure(vm, this, functionConstructor), m_generatorFunctionPrototype.get());
@@ -468,16 +611,12 @@ m_ ## lowerName ## Prototype->putDirectWithoutTransition(vm, vm.propertyNames->c
     putDirectWithoutTransition(vm, vm.propertyNames->Function, functionConstructor, DontEnum);
     putDirectWithoutTransition(vm, vm.propertyNames->Array, arrayConstructor, DontEnum);
     putDirectWithoutTransition(vm, vm.propertyNames->RegExp, m_regExpConstructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->EvalError, m_evalErrorConstructor.get(), DontEnum);
     putDirectWithoutTransition(vm, vm.propertyNames->RangeError, m_rangeErrorConstructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->ReferenceError, m_referenceErrorConstructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->SyntaxError, m_syntaxErrorConstructor.get(), DontEnum);
     putDirectWithoutTransition(vm, vm.propertyNames->TypeError, m_typeErrorConstructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->URIError, m_URIErrorConstructor.get(), DontEnum);
 
-    putDirectWithoutTransition(vm, vm.propertyNames->Proxy, ProxyConstructor::create(vm, ProxyConstructor::createStructure(vm, this, m_functionPrototype.get())), DontEnum);
-    
-    
+    putDirectWithoutTransition(vm, vm.propertyNames->ObjectPrivateName, objectConstructor, DontEnum | DontDelete | ReadOnly);
+    putDirectWithoutTransition(vm, vm.propertyNames->ArrayPrivateName, arrayConstructor, DontEnum | DontDelete | ReadOnly);
+
 #define PUT_CONSTRUCTOR_FOR_SIMPLE_TYPE(capitalName, lowerName, properName, instanceType, jsName) \
 putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Constructor, DontEnum); \
 
@@ -493,44 +632,11 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
     IntlObject* intl = IntlObject::create(vm, this, IntlObject::createStructure(vm, this, m_objectPrototype.get()));
     putDirectWithoutTransition(vm, vm.propertyNames->Intl, intl, DontEnum);
 #endif // ENABLE(INTL)
-    putDirectWithoutTransition(vm, vm.propertyNames->JSON, JSONObject::create(vm, JSONObject::createStructure(vm, this, m_objectPrototype.get())), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->Math, MathObject::create(vm, this, MathObject::createStructure(vm, this, m_objectPrototype.get())), DontEnum);
     ReflectObject* reflectObject = ReflectObject::create(vm, this, ReflectObject::createStructure(vm, this, m_objectPrototype.get()));
     putDirectWithoutTransition(vm, vm.propertyNames->Reflect, reflectObject, DontEnum);
 
     putDirectWithoutTransition(vm, vm.propertyNames->console, ConsoleObject::create(vm, this, ConsoleObject::createStructure(vm, this, m_objectPrototype.get())), DontEnum);
 
-    JSTypedArrayViewConstructor* typedArraySuperConstructor = JSTypedArrayViewConstructor::create(vm, this, JSTypedArrayViewConstructor::createStructure(vm, this, m_functionPrototype.get()), typedArrayProto, speciesGetterSetter);
-    typedArrayProto->putDirectWithoutTransition(vm, vm.propertyNames->constructor, typedArraySuperConstructor, DontEnum);
-
-    m_typedArrays[toIndex(TypeInt8)].constructor.set(vm , this, JSInt8ArrayConstructor::create(vm, this, JSInt8ArrayConstructor::createStructure(vm, this, typedArraySuperConstructor), m_typedArrays[toIndex(TypeInt8)].prototype.get(), ASCIILiteral("Int8Array"), typedArrayConstructorAllocateInt8ArrayCodeGenerator(vm)));
-    m_typedArrays[toIndex(TypeInt16)].constructor.set(vm, this, JSInt16ArrayConstructor::create(vm, this, JSInt16ArrayConstructor::createStructure(vm, this, typedArraySuperConstructor), m_typedArrays[toIndex(TypeInt16)].prototype.get(), ASCIILiteral("Int16Array"), typedArrayConstructorAllocateInt16ArrayCodeGenerator(vm)));
-    m_typedArrays[toIndex(TypeInt32)].constructor.set(vm, this, JSInt32ArrayConstructor::create(vm, this, JSInt32ArrayConstructor::createStructure(vm, this, typedArraySuperConstructor), m_typedArrays[toIndex(TypeInt32)].prototype.get(), ASCIILiteral("Int32Array"), typedArrayConstructorAllocateInt32ArrayCodeGenerator(vm)));
-    m_typedArrays[toIndex(TypeUint8)].constructor.set(vm, this, JSUint8ArrayConstructor::create(vm, this, JSUint8ArrayConstructor::createStructure(vm, this, typedArraySuperConstructor), m_typedArrays[toIndex(TypeUint8)].prototype.get(), ASCIILiteral("Uint8Array"), typedArrayConstructorAllocateUint8ArrayCodeGenerator(vm)));
-    m_typedArrays[toIndex(TypeUint8Clamped)].constructor.set(vm, this, JSUint8ClampedArrayConstructor::create(vm, this, JSUint8ClampedArrayConstructor::createStructure(vm, this, typedArraySuperConstructor), m_typedArrays[toIndex(TypeUint8Clamped)].prototype.get(), ASCIILiteral("Uint8ClampedArray"), typedArrayConstructorAllocateUint8ClampedArrayCodeGenerator(vm)));
-    m_typedArrays[toIndex(TypeUint16)].constructor.set(vm, this, JSUint16ArrayConstructor::create(vm, this, JSUint16ArrayConstructor::createStructure(vm, this, typedArraySuperConstructor), m_typedArrays[toIndex(TypeUint16)].prototype.get(), ASCIILiteral("Uint16Array"), typedArrayConstructorAllocateUint16ArrayCodeGenerator(vm)));
-    m_typedArrays[toIndex(TypeUint32)].constructor.set(vm, this, JSUint32ArrayConstructor::create(vm, this, JSUint32ArrayConstructor::createStructure(vm, this, typedArraySuperConstructor), m_typedArrays[toIndex(TypeUint32)].prototype.get(), ASCIILiteral("Uint32Array"), typedArrayConstructorAllocateUint32ArrayCodeGenerator(vm)));
-    m_typedArrays[toIndex(TypeFloat32)].constructor.set(vm, this, JSFloat32ArrayConstructor::create(vm, this, JSFloat32ArrayConstructor::createStructure(vm, this, typedArraySuperConstructor), m_typedArrays[toIndex(TypeFloat32)].prototype.get(), ASCIILiteral("Float32Array"), typedArrayConstructorAllocateFloat32ArrayCodeGenerator(vm)));
-    m_typedArrays[toIndex(TypeFloat64)].constructor.set(vm, this, JSFloat64ArrayConstructor::create(vm, this, JSFloat64ArrayConstructor::createStructure(vm, this, typedArraySuperConstructor), m_typedArrays[toIndex(TypeFloat64)].prototype.get(), ASCIILiteral("Float64Array"), typedArrayConstructorAllocateFloat64ArrayCodeGenerator(vm)));
-    m_typedArrays[toIndex(TypeDataView)].constructor.set(vm, this, JSDataViewConstructor::create(vm, this, JSDataViewConstructor::createStructure(vm, this, m_functionPrototype.get()), m_typedArrays[toIndex(TypeDataView)].prototype.get(), ASCIILiteral("DataView"), nullptr));
-    
-    for (unsigned typedArrayIndex = NUMBER_OF_TYPED_ARRAY_TYPES; typedArrayIndex--;) {
-        m_typedArrays[typedArrayIndex].prototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, m_typedArrays[typedArrayIndex].constructor.get(), DontEnum);
-        putDirectWithoutTransition(vm, Identifier::fromString(exec, m_typedArrays[typedArrayIndex].constructor.get()->name(exec)), m_typedArrays[typedArrayIndex].constructor.get(), DontEnum);
-    }
-
-    putDirectWithoutTransition(vm, vm.propertyNames->Int8ArrayPrivateName, m_typedArrays[toIndex(TypeInt8)].constructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->Int16ArrayPrivateName, m_typedArrays[toIndex(TypeInt16)].constructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->Int32ArrayPrivateName, m_typedArrays[toIndex(TypeInt32)].constructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->Uint8ArrayPrivateName, m_typedArrays[toIndex(TypeUint8)].constructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->Uint8ClampedArrayPrivateName, m_typedArrays[toIndex(TypeUint8Clamped)].constructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->Uint16ArrayPrivateName, m_typedArrays[toIndex(TypeUint16)].constructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->Uint32ArrayPrivateName, m_typedArrays[toIndex(TypeUint32)].constructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->Float32ArrayPrivateName, m_typedArrays[toIndex(TypeFloat32)].constructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->Float64ArrayPrivateName, m_typedArrays[toIndex(TypeFloat64)].constructor.get(), DontEnum);
-    putDirectWithoutTransition(vm, vm.propertyNames->ObjectPrivateName, objectConstructor, DontEnum | DontDelete | ReadOnly);
-    putDirectWithoutTransition(vm, vm.propertyNames->ArrayPrivateName, arrayConstructor, DontEnum | DontDelete | ReadOnly);
-
     m_moduleLoader.set(vm, this, ModuleLoaderObject::create(vm, this, ModuleLoaderObject::createStructure(vm, this, m_objectPrototype.get())));
     if (Options::exposeInternalModuleLoader())
         putDirectWithoutTransition(vm, vm.propertyNames->Loader, m_moduleLoader.get(), DontEnum);
@@ -900,24 +1006,6 @@ bool JSGlobalObject::stringPrototypeChainIsSane()
         && objectPrototypeIsSane();
 }
 
-void JSGlobalObject::createThrowTypeError(VM& vm)
-{
-    JSFunction* thrower = JSFunction::create(vm, this, 0, String(), globalFuncThrowTypeError);
-    GetterSetter* getterSetter = GetterSetter::create(vm, this);
-    getterSetter->setGetter(vm, this, thrower);
-    getterSetter->setSetter(vm, this, thrower);
-    m_throwTypeErrorGetterSetter.set(vm, this, getterSetter);
-}
-
-void JSGlobalObject::createThrowTypeErrorArgumentsAndCaller(VM& vm)
-{
-    JSFunction* thrower = JSFunction::create(vm, this, 0, String(), globalFuncThrowTypeErrorArgumentsAndCaller);
-    GetterSetter* getterSetter = GetterSetter::create(vm, this);
-    getterSetter->setGetter(vm, this, thrower);
-    getterSetter->setSetter(vm, this, thrower);
-    m_throwTypeErrorArgumentsAndCallerGetterSetter.set(vm, this, getterSetter);
-}
-
 // Set prototype, and also insert the object prototype at the end of the chain.
 void JSGlobalObject::resetPrototype(VM& vm, JSValue prototype)
 {
@@ -944,15 +1032,16 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_globalCallee);
     visitor.append(&thisObject->m_regExpConstructor);
     visitor.append(&thisObject->m_errorConstructor);
-    visitor.append(&thisObject->m_evalErrorConstructor);
+    visitor.append(&thisObject->m_nativeErrorPrototypeStructure);
+    visitor.append(&thisObject->m_nativeErrorStructure);
+    thisObject->m_evalErrorConstructor.visit(visitor);
     visitor.append(&thisObject->m_rangeErrorConstructor);
-    visitor.append(&thisObject->m_referenceErrorConstructor);
-    visitor.append(&thisObject->m_syntaxErrorConstructor);
+    thisObject->m_referenceErrorConstructor.visit(visitor);
+    thisObject->m_syntaxErrorConstructor.visit(visitor);
     visitor.append(&thisObject->m_typeErrorConstructor);
-    visitor.append(&thisObject->m_URIErrorConstructor);
+    thisObject->m_URIErrorConstructor.visit(visitor);
     visitor.append(&thisObject->m_objectConstructor);
     visitor.append(&thisObject->m_promiseConstructor);
-    visitor.append(&thisObject->m_internalPromiseConstructor);
 
     visitor.append(&thisObject->m_nullGetterFunction);
     visitor.append(&thisObject->m_nullSetterFunction);
@@ -962,12 +1051,12 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_callFunction);
     visitor.append(&thisObject->m_applyFunction);
     visitor.append(&thisObject->m_definePropertyFunction);
-    visitor.append(&thisObject->m_arrayProtoValuesFunction);
-    visitor.append(&thisObject->m_initializePromiseFunction);
+    thisObject->m_arrayProtoValuesFunction.visit(visitor);
+    thisObject->m_initializePromiseFunction.visit(visitor);
     visitor.append(&thisObject->m_newPromiseCapabilityFunction);
     visitor.append(&thisObject->m_functionProtoHasInstanceSymbolFunction);
-    visitor.append(&thisObject->m_throwTypeErrorGetterSetter);
-    visitor.append(&thisObject->m_throwTypeErrorArgumentsAndCallerGetterSetter);
+    thisObject->m_throwTypeErrorGetterSetter.visit(visitor);
+    thisObject->m_throwTypeErrorArgumentsAndCallerGetterSetter.visit(visitor);
     visitor.append(&thisObject->m_moduleLoader);
 
     visitor.append(&thisObject->m_objectPrototype);
@@ -978,11 +1067,11 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_generatorFunctionPrototype);
     visitor.append(&thisObject->m_generatorPrototype);
 
-    visitor.append(&thisObject->m_debuggerScopeStructure);
-    visitor.append(&thisObject->m_withScopeStructure);
+    thisObject->m_debuggerScopeStructure.visit(visitor);
+    thisObject->m_withScopeStructure.visit(visitor);
     visitor.append(&thisObject->m_strictEvalActivationStructure);
     visitor.append(&thisObject->m_lexicalEnvironmentStructure);
-    visitor.append(&thisObject->m_moduleEnvironmentStructure);
+    thisObject->m_moduleEnvironmentStructure.visit(visitor);
     visitor.append(&thisObject->m_directArgumentsStructure);
     visitor.append(&thisObject->m_scopedArgumentsStructure);
     visitor.append(&thisObject->m_clonedArgumentsStructure);
@@ -991,24 +1080,23 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
         visitor.append(&thisObject->m_originalArrayStructureForIndexingShape[i]);
     for (unsigned i = 0; i < NumberOfIndexingShapes; ++i)
         visitor.append(&thisObject->m_arrayStructureForIndexingShapeDuringAllocation[i]);
-    visitor.append(&thisObject->m_booleanObjectStructure);
-    visitor.append(&thisObject->m_callbackConstructorStructure);
-    visitor.append(&thisObject->m_callbackFunctionStructure);
-    visitor.append(&thisObject->m_callbackObjectStructure);
+    thisObject->m_callbackConstructorStructure.visit(visitor);
+    thisObject->m_callbackFunctionStructure.visit(visitor);
+    thisObject->m_callbackObjectStructure.visit(visitor);
     visitor.append(&thisObject->m_propertyNameIteratorStructure);
 #if JSC_OBJC_API_ENABLED
-    visitor.append(&thisObject->m_objcCallbackFunctionStructure);
-    visitor.append(&thisObject->m_objcWrapperObjectStructure);
+    thisObject->m_objcCallbackFunctionStructure.visit(visitor);
+    thisObject->m_objcWrapperObjectStructure.visit(visitor);
 #endif
-    visitor.append(&thisObject->m_nullPrototypeObjectStructure);
+    thisObject->m_nullPrototypeObjectStructure.visit(visitor);
     visitor.append(&thisObject->m_errorStructure);
     visitor.append(&thisObject->m_calleeStructure);
     visitor.append(&thisObject->m_functionStructure);
-    visitor.append(&thisObject->m_boundSlotBaseFunctionStructure);
-    visitor.append(&thisObject->m_boundFunctionStructure);
+    thisObject->m_boundSlotBaseFunctionStructure.visit(visitor);
+    thisObject->m_boundFunctionStructure.visit(visitor);
     visitor.append(&thisObject->m_getterSetterStructure);
-    visitor.append(&thisObject->m_nativeStdFunctionStructure);
-    visitor.append(&thisObject->m_namedFunctionStructure);
+    thisObject->m_nativeStdFunctionStructure.visit(visitor);
+    thisObject->m_namedFunctionStructure.visit(visitor);
     visitor.append(&thisObject->m_symbolObjectStructure);
     visitor.append(&thisObject->m_regExpStructure);
     visitor.append(&thisObject->m_generatorFunctionStructure);
@@ -1018,7 +1106,6 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_moduleRecordStructure);
     visitor.append(&thisObject->m_moduleNamespaceObjectStructure);
     visitor.append(&thisObject->m_dollarVMStructure);
-    visitor.append(&thisObject->m_internalFunctionStructure);
     visitor.append(&thisObject->m_proxyObjectStructure);
     visitor.append(&thisObject->m_callableProxyObjectStructure);
     visitor.append(&thisObject->m_proxyRevokeStructure);
@@ -1031,15 +1118,23 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_ ## properName ## Structure); \
 
     FOR_EACH_SIMPLE_BUILTIN_TYPE(VISIT_SIMPLE_TYPE)
-    FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(VISIT_SIMPLE_TYPE)
 
 #undef VISIT_SIMPLE_TYPE
 
-    for (unsigned i = NUMBER_OF_TYPED_ARRAY_TYPES; i--;) {
-        visitor.append(&thisObject->m_typedArrays[i].prototype);
-        visitor.append(&thisObject->m_typedArrays[i].constructor);
-        visitor.append(&thisObject->m_typedArrays[i].structure);
-    }
+#define VISIT_LAZY_TYPE(CapitalName, lowerName, properName, instanceType, jsName) \
+    thisObject->m_ ## properName ## Structure.visit(visitor);
+    
+    FOR_EACH_LAZY_BUILTIN_TYPE(VISIT_LAZY_TYPE)
+    FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(VISIT_LAZY_TYPE)
+
+#undef VISIT_LAZY_TYPE
+
+    for (unsigned i = NUMBER_OF_TYPED_ARRAY_TYPES; i--;)
+        thisObject->lazyTypedArrayStructure(indexToTypedArrayType(i)).visit(visitor);
+    
+    visitor.append(&thisObject->m_speciesGetterSetter);
+    thisObject->m_typedArrayProto.visit(visitor);
+    thisObject->m_typedArraySuperConstructor.visit(visitor);
 }
 
 JSValue JSGlobalObject::toThis(JSCell*, ExecState* exec, ECMAMode ecmaMode)
@@ -1081,7 +1176,7 @@ void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
 bool JSGlobalObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
     JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
-    if (getStaticFunctionSlot<Base>(exec, globalObjectTable, thisObject, propertyName, slot))
+    if (getStaticPropertySlot<JSGlobalObject, Base>(exec, globalObjectTable, thisObject, propertyName, slot))
         return true;
     return symbolTableGet(thisObject, propertyName, slot);
 }
index 82749ce..00b0f07 100644 (file)
@@ -31,6 +31,8 @@
 #include "JSProxy.h"
 #include "JSSegmentedVariableObject.h"
 #include "JSWeakObjectMapRefInternal.h"
+#include "LazyProperty.h"
+#include "LazyClassStructure.h"
 #include "NumberPrototype.h"
 #include "RuntimeFlags.h"
 #include "SpecialPointer.h"
@@ -75,6 +77,8 @@ class JSPromise;
 class JSPromiseConstructor;
 class JSPromisePrototype;
 class JSStack;
+class JSTypedArrayViewConstructor;
+class JSTypedArrayViewPrototype;
 class LLIntOffsetsExtractor;
 class Microtask;
 class ModuleLoaderObject;
@@ -97,18 +101,13 @@ struct HashTable;
 #define DEFINE_STANDARD_BUILTIN(macro, upperName, lowerName) macro(upperName, lowerName, lowerName, JS ## upperName, upperName)
 
 #define FOR_EACH_SIMPLE_BUILTIN_TYPE_WITH_CONSTRUCTOR(macro) \
-    macro(Set, set, set, JSSet, Set) \
-    macro(Map, map, map, JSMap, Map) \
-    macro(Date, date, date, DateInstance, Date) \
     macro(String, string, stringObject, StringObject, String) \
     macro(Symbol, symbol, symbolObject, SymbolObject, Symbol) \
-    macro(Boolean, boolean, booleanObject, BooleanObject, Boolean) \
     macro(Number, number, numberObject, NumberObject, Number) \
     macro(Error, error, error, ErrorInstance, Error) \
+    macro(Map, map, map, JSMap, Map) \
     macro(JSPromise, promise, promise, JSPromise, Promise) \
     macro(JSArrayBuffer, arrayBuffer, arrayBuffer, JSArrayBuffer, ArrayBuffer) \
-    DEFINE_STANDARD_BUILTIN(macro, WeakMap, weakMap) \
-    DEFINE_STANDARD_BUILTIN(macro, WeakSet, weakSet) \
 
 #define FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(macro) \
     DEFINE_STANDARD_BUILTIN(macro, MapIterator, mapIterator) \
@@ -123,6 +122,13 @@ struct HashTable;
     FOR_EACH_SIMPLE_BUILTIN_TYPE_WITH_CONSTRUCTOR(macro) \
     macro(JSInternalPromise, internalPromise, internalPromise, JSInternalPromise, InternalPromise) \
 
+#define FOR_EACH_LAZY_BUILTIN_TYPE(macro) \
+    macro(Set, set, set, JSSet, Set) \
+    macro(Date, date, date, DateInstance, Date) \
+    macro(Boolean, boolean, booleanObject, BooleanObject, Boolean) \
+    DEFINE_STANDARD_BUILTIN(macro, WeakMap, weakMap) \
+    DEFINE_STANDARD_BUILTIN(macro, WeakSet, weakSet) \
+
 #define DECLARE_SIMPLE_BUILTIN_TYPE(capitalName, lowerName, properName, instanceType, jsName) \
     class JS ## capitalName; \
     class capitalName ## Prototype; \
@@ -130,10 +136,15 @@ struct HashTable;
 
 class IteratorPrototype;
 FOR_EACH_SIMPLE_BUILTIN_TYPE(DECLARE_SIMPLE_BUILTIN_TYPE)
+FOR_EACH_LAZY_BUILTIN_TYPE(DECLARE_SIMPLE_BUILTIN_TYPE)
 FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(DECLARE_SIMPLE_BUILTIN_TYPE)
 
 #undef DECLARE_SIMPLE_BUILTIN_TYPE
 
+class JSInternalPromise;
+class InternalPromisePrototype;
+class InternalPromiseConstructor;
+
 typedef Vector<ExecState*, 16> ExecStateStack;
 
 struct GlobalObjectMethodTable {
@@ -196,7 +207,11 @@ private:
         OpaqueJSClassDataMap opaqueJSClassData;
     };
 
-protected:
+// Our hashtable code-generator tries to access these properties, so we make them public.
+// However, we'd like it better if they could be protected.
+public:
+    template<typename T> using Initializer = typename LazyProperty<JSGlobalObject, T>::Initializer;
+    
     Register m_globalCallFrame[JSStack::CallFrameHeaderSize];
 
     WriteBarrier<JSObject> m_globalThis;
@@ -205,12 +220,14 @@ protected:
     WriteBarrier<JSObject> m_globalCallee;
     WriteBarrier<RegExpConstructor> m_regExpConstructor;
     WriteBarrier<ErrorConstructor> m_errorConstructor;
-    WriteBarrier<NativeErrorConstructor> m_evalErrorConstructor;
+    WriteBarrier<Structure> m_nativeErrorPrototypeStructure;
+    WriteBarrier<Structure> m_nativeErrorStructure;
+    LazyProperty<JSGlobalObject, NativeErrorConstructor> m_evalErrorConstructor;
     WriteBarrier<NativeErrorConstructor> m_rangeErrorConstructor;
-    WriteBarrier<NativeErrorConstructor> m_referenceErrorConstructor;
-    WriteBarrier<NativeErrorConstructor> m_syntaxErrorConstructor;
+    LazyProperty<JSGlobalObject, NativeErrorConstructor> m_referenceErrorConstructor;
+    LazyProperty<JSGlobalObject, NativeErrorConstructor> m_syntaxErrorConstructor;
     WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor;
-    WriteBarrier<NativeErrorConstructor> m_URIErrorConstructor;
+    LazyProperty<JSGlobalObject, NativeErrorConstructor> m_URIErrorConstructor;
     WriteBarrier<ObjectConstructor> m_objectConstructor;
     WriteBarrier<JSPromiseConstructor> m_promiseConstructor;
     WriteBarrier<JSInternalPromiseConstructor> m_internalPromiseConstructor;
@@ -224,16 +241,16 @@ protected:
     WriteBarrier<JSFunction> m_callFunction;
     WriteBarrier<JSFunction> m_applyFunction;
     WriteBarrier<JSFunction> m_definePropertyFunction;
-    WriteBarrier<JSFunction> m_arrayProtoValuesFunction;
-    WriteBarrier<JSFunction> m_initializePromiseFunction;
+    LazyProperty<JSGlobalObject, JSFunction> m_arrayProtoValuesFunction;
+    LazyProperty<JSGlobalObject, JSFunction> m_initializePromiseFunction;
     WriteBarrier<JSFunction> m_newPromiseCapabilityFunction;
     WriteBarrier<JSFunction> m_functionProtoHasInstanceSymbolFunction;
+    LazyProperty<JSGlobalObject, GetterSetter> m_throwTypeErrorGetterSetter;
     WriteBarrier<JSObject> m_regExpProtoExec;
     WriteBarrier<JSObject> m_regExpProtoSymbolReplace;
     WriteBarrier<JSObject> m_regExpProtoGlobalGetter;
     WriteBarrier<JSObject> m_regExpProtoUnicodeGetter;
-    WriteBarrier<GetterSetter> m_throwTypeErrorGetterSetter;
-    WriteBarrier<GetterSetter> m_throwTypeErrorArgumentsAndCallerGetterSetter;
+    LazyProperty<JSGlobalObject, GetterSetter> m_throwTypeErrorArgumentsAndCallerGetterSetter;
 
     WriteBarrier<ModuleLoaderObject> m_moduleLoader;
 
@@ -245,11 +262,11 @@ protected:
     WriteBarrier<GeneratorFunctionPrototype> m_generatorFunctionPrototype;
     WriteBarrier<GeneratorPrototype> m_generatorPrototype;
 
-    WriteBarrier<Structure> m_debuggerScopeStructure;
-    WriteBarrier<Structure> m_withScopeStructure;
+    LazyProperty<JSGlobalObject, Structure> m_debuggerScopeStructure;
+    LazyProperty<JSGlobalObject, Structure> m_withScopeStructure;
     WriteBarrier<Structure> m_strictEvalActivationStructure;
     WriteBarrier<Structure> m_lexicalEnvironmentStructure;
-    WriteBarrier<Structure> m_moduleEnvironmentStructure;
+    LazyProperty<JSGlobalObject, Structure> m_moduleEnvironmentStructure;
     WriteBarrier<Structure> m_directArgumentsStructure;
     WriteBarrier<Structure> m_scopedArgumentsStructure;
     WriteBarrier<Structure> m_clonedArgumentsStructure;
@@ -262,28 +279,27 @@ protected:
     // These structures will differ from the originals list above when we are having a bad time.
     WriteBarrier<Structure> m_arrayStructureForIndexingShapeDuringAllocation[NumberOfIndexingShapes];
 
-    WriteBarrier<Structure> m_callbackConstructorStructure;
-    WriteBarrier<Structure> m_callbackFunctionStructure;
-    WriteBarrier<Structure> m_callbackObjectStructure;
+    LazyProperty<JSGlobalObject, Structure> m_callbackConstructorStructure;
+    LazyProperty<JSGlobalObject, Structure> m_callbackFunctionStructure;
+    LazyProperty<JSGlobalObject, Structure> m_callbackObjectStructure;
     WriteBarrier<Structure> m_propertyNameIteratorStructure;
 #if JSC_OBJC_API_ENABLED
-    WriteBarrier<Structure> m_objcCallbackFunctionStructure;
-    WriteBarrier<Structure> m_objcWrapperObjectStructure;
+    LazyProperty<JSGlobalObject, Structure> m_objcCallbackFunctionStructure;
+    LazyProperty<JSGlobalObject, Structure> m_objcWrapperObjectStructure;
 #endif
-    WriteBarrier<Structure> m_nullPrototypeObjectStructure;
+    LazyProperty<JSGlobalObject, Structure> m_nullPrototypeObjectStructure;
     WriteBarrier<Structure> m_calleeStructure;
     WriteBarrier<Structure> m_functionStructure;
-    WriteBarrier<Structure> m_boundFunctionStructure;
-    WriteBarrier<Structure> m_boundSlotBaseFunctionStructure;
+    LazyProperty<JSGlobalObject, Structure> m_boundFunctionStructure;
+    LazyProperty<JSGlobalObject, Structure> m_boundSlotBaseFunctionStructure;
     WriteBarrier<Structure> m_getterSetterStructure;
-    WriteBarrier<Structure> m_nativeStdFunctionStructure;
-    WriteBarrier<Structure> m_namedFunctionStructure;
+    LazyProperty<JSGlobalObject, Structure> m_nativeStdFunctionStructure;
+    LazyProperty<JSGlobalObject, Structure> m_namedFunctionStructure;
     PropertyOffset m_functionNameOffset;
     WriteBarrier<Structure> m_privateNameStructure;
     WriteBarrier<Structure> m_regExpStructure;
     WriteBarrier<Structure> m_generatorFunctionStructure;
     WriteBarrier<Structure> m_dollarVMStructure;
-    WriteBarrier<Structure> m_internalFunctionStructure;
     WriteBarrier<Structure> m_iteratorResultObjectStructure;
     WriteBarrier<Structure> m_regExpMatchesArrayStructure;
     WriteBarrier<Structure> m_regExpMatchesArraySlowPutStructure;
@@ -301,17 +317,27 @@ protected:
     WriteBarrier<Structure> m_ ## properName ## Structure;
 
     FOR_EACH_SIMPLE_BUILTIN_TYPE(DEFINE_STORAGE_FOR_SIMPLE_TYPE)
-    FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(DEFINE_STORAGE_FOR_SIMPLE_TYPE)
 
 #undef DEFINE_STORAGE_FOR_SIMPLE_TYPE
 
-    struct TypedArrayData {
-        WriteBarrier<JSObject> prototype;
-        WriteBarrier<InternalFunction> constructor;
-        WriteBarrier<Structure> structure;
-    };
+#define DEFINE_STORAGE_FOR_ITERATOR_TYPE(capitalName, lowerName, properName, instanceType, jsName) \
+    LazyProperty<JSGlobalObject, Structure> m_ ## properName ## Structure;
+    FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(DEFINE_STORAGE_FOR_ITERATOR_TYPE)
+#undef DEFINE_STORAGE_FOR_ITERATOR_TYPE
     
-    std::array<TypedArrayData, NUMBER_OF_TYPED_ARRAY_TYPES> m_typedArrays;
+#define DEFINE_STORAGE_FOR_LAZY_TYPE(capitalName, lowerName, properName, instanceType, jsName) \
+    LazyClassStructure m_ ## properName ## Structure;
+    FOR_EACH_LAZY_BUILTIN_TYPE(DEFINE_STORAGE_FOR_LAZY_TYPE)
+#undef DEFINE_STORAGE_FOR_LAZY_TYPE
+
+    WriteBarrier<GetterSetter> m_speciesGetterSetter;
+    
+    LazyProperty<JSGlobalObject, JSTypedArrayViewPrototype> m_typedArrayProto;
+    LazyProperty<JSGlobalObject, JSTypedArrayViewConstructor> m_typedArraySuperConstructor;
+    
+#define DECLARE_TYPED_ARRAY_TYPE_STRUCTURE(name) LazyClassStructure m_typedArray ## name;
+    FOR_EACH_TYPED_ARRAY_TYPE(DECLARE_TYPED_ARRAY_TYPE_STRUCTURE)
+#undef DECLARE_TYPED_ARRAY_TYPE_STRUCTURE
 
     JSCell* m_specialPointers[Special::TableSize]; // Special pointers used by the LLInt and JIT.
     JSCell* m_linkTimeConstants[LinkTimeConstantCount];
@@ -438,12 +464,12 @@ public:
     ObjectConstructor* objectConstructor() const { return m_objectConstructor.get(); }
     JSPromiseConstructor* promiseConstructor() const { return m_promiseConstructor.get(); }
     JSInternalPromiseConstructor* internalPromiseConstructor() const { return m_internalPromiseConstructor.get(); }
-    NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); }
+    NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(this); }
     NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); }
-    NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); }
-    NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(); }
+    NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(this); }
+    NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(this); }
     NativeErrorConstructor* typeErrorConstructor() const { return m_typeErrorConstructor.get(); }
-    NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(); }
+    NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(this); }
 
     NullGetterFunction* nullGetterFunction() const { return m_nullGetterFunction.get(); }
     NullSetterFunction* nullSetterFunction() const { return m_nullSetterFunction.get(); }
@@ -454,26 +480,22 @@ public:
     JSFunction* callFunction() const { return m_callFunction.get(); }
     JSFunction* applyFunction() const { return m_applyFunction.get(); }
     JSFunction* definePropertyFunction() const { return m_definePropertyFunction.get(); }
-    JSFunction* arrayProtoValuesFunction() const { return m_arrayProtoValuesFunction.get(); }
-    JSFunction* initializePromiseFunction() const { return m_initializePromiseFunction.get(); }
+    JSFunction* arrayProtoValuesFunction() const { return m_arrayProtoValuesFunction.get(this); }
+    JSFunction* initializePromiseFunction() const { return m_initializePromiseFunction.get(this); }
     JSFunction* newPromiseCapabilityFunction() const { return m_newPromiseCapabilityFunction.get(); }
     JSFunction* functionProtoHasInstanceSymbolFunction() const { return m_functionProtoHasInstanceSymbolFunction.get(); }
     JSObject* regExpProtoExecFunction() const { return m_regExpProtoExec.get(); }
     JSObject* regExpProtoSymbolReplaceFunction() const { return m_regExpProtoSymbolReplace.get(); }
     JSObject* regExpProtoGlobalGetter() const { return m_regExpProtoGlobalGetter.get(); }
     JSObject* regExpProtoUnicodeGetter() const { return m_regExpProtoUnicodeGetter.get(); }
-    GetterSetter* throwTypeErrorGetterSetter(VM& vm)
+    GetterSetter* throwTypeErrorGetterSetter()
     {
-        if (!m_throwTypeErrorGetterSetter)
-            createThrowTypeError(vm);
-        return m_throwTypeErrorGetterSetter.get();
+        return m_throwTypeErrorGetterSetter.get(this);
     }
 
-    GetterSetter* throwTypeErrorArgumentsAndCallerGetterSetter(VM& vm)
+    GetterSetter* throwTypeErrorArgumentsAndCallerGetterSetter()
     {
-        if (!m_throwTypeErrorArgumentsAndCallerGetterSetter)
-            createThrowTypeErrorArgumentsAndCaller(vm);
-        return m_throwTypeErrorArgumentsAndCallerGetterSetter.get();
+        return m_throwTypeErrorArgumentsAndCallerGetterSetter.get(this);
     }
     
     ModuleLoaderObject* moduleLoader() const { return m_moduleLoader.get(); }
@@ -481,22 +503,22 @@ public:
     ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); }
     FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); }
     ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); }
-    BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); }
+    JSObject* booleanPrototype() const { return m_booleanObjectStructure.prototype(this); }
     StringPrototype* stringPrototype() const { return m_stringPrototype.get(); }
     SymbolPrototype* symbolPrototype() const { return m_symbolPrototype.get(); }
-    NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); }
-    DatePrototype* datePrototype() const { return m_datePrototype.get(); }
+    JSObject* numberPrototype() const { return m_numberPrototype.get(); }
+    JSObject* datePrototype() const { return m_dateStructure.prototype(this); }
     RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); }
     ErrorPrototype* errorPrototype() const { return m_errorPrototype.get(); }
     IteratorPrototype* iteratorPrototype() const { return m_iteratorPrototype.get(); }
     GeneratorFunctionPrototype* generatorFunctionPrototype() const { return m_generatorFunctionPrototype.get(); }
     GeneratorPrototype* generatorPrototype() const { return m_generatorPrototype.get(); }
 
-    Structure* debuggerScopeStructure() const { return m_debuggerScopeStructure.get(); }
-    Structure* withScopeStructure() const { return m_withScopeStructure.get(); }
+    Structure* debuggerScopeStructure() const { return m_debuggerScopeStructure.get(this); }
+    Structure* withScopeStructure() const { return m_withScopeStructure.get(this); }
     Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); }
     Structure* activationStructure() const { return m_lexicalEnvironmentStructure.get(); }
-    Structure* moduleEnvironmentStructure() const { return m_moduleEnvironmentStructure.get(); }
+    Structure* moduleEnvironmentStructure() const { return m_moduleEnvironmentStructure.get(this); }
     Structure* directArgumentsStructure() const { return m_directArgumentsStructure.get(); }
     Structure* scopedArgumentsStructure() const { return m_scopedArgumentsStructure.get(); }
     Structure* clonedArgumentsStructure() const { return m_clonedArgumentsStructure.get(); }
@@ -525,33 +547,32 @@ public:
         return originalArrayStructureForIndexingType(structure->indexingType() | IsArray) == structure;
     }
         
-    Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); }
-    Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); }
-    Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); }
-    Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); }
+    Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(this); }
+    Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(this); }
+    Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(this); }
+    Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(this); }
     Structure* propertyNameIteratorStructure() const { return m_propertyNameIteratorStructure.get(); }
 #if JSC_OBJC_API_ENABLED
-    Structure* objcCallbackFunctionStructure() const { return m_objcCallbackFunctionStructure.get(); }
-    Structure* objcWrapperObjectStructure() const { return m_objcWrapperObjectStructure.get(); }
+    Structure* objcCallbackFunctionStructure() const { return m_objcCallbackFunctionStructure.get(this); }
+    Structure* objcWrapperObjectStructure() const { return m_objcWrapperObjectStructure.get(this); }
 #endif
-    Structure* dateStructure() const { return m_dateStructure.get(); }
-    Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); }
+    Structure* dateStructure() const { return m_dateStructure.get(this); }
+    Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(this); }
     Structure* errorStructure() const { return m_errorStructure.get(); }
     Structure* calleeStructure() const { return m_calleeStructure.get(); }
     Structure* functionStructure() const { return m_functionStructure.get(); }
-    Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(); }
-    Structure* boundSlotBaseFunctionStructure() const { return m_boundSlotBaseFunctionStructure.get(); }
+    Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(this); }
+    Structure* boundSlotBaseFunctionStructure() const { return m_boundSlotBaseFunctionStructure.get(this); }
     Structure* getterSetterStructure() const { return m_getterSetterStructure.get(); }
-    Structure* nativeStdFunctionStructure() const { return m_nativeStdFunctionStructure.get(); }
-    Structure* namedFunctionStructure() const { return m_namedFunctionStructure.get(); }
+    Structure* nativeStdFunctionStructure() const { return m_nativeStdFunctionStructure.get(this); }
+    Structure* namedFunctionStructure() const { return m_namedFunctionStructure.get(this); }
     PropertyOffset functionNameOffset() const { return m_functionNameOffset; }
     Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); }
     Structure* privateNameStructure() const { return m_privateNameStructure.get(); }
-    Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); }
     Structure* mapStructure() const { return m_mapStructure.get(); }
     Structure* regExpStructure() const { return m_regExpStructure.get(); }
     Structure* generatorFunctionStructure() const { return m_generatorFunctionStructure.get(); }
-    Structure* setStructure() const { return m_setStructure.get(); }
+    Structure* setStructure() const { return m_setStructure.get(this); }
     Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
     Structure* symbolObjectStructure() const { return m_symbolObjectStructure.get(); }
     Structure* iteratorResultObjectStructure() const { return m_iteratorResultObjectStructure.get(); }
@@ -596,25 +617,60 @@ public:
     Structure* properName ## Structure() { return m_ ## properName ## Structure.get(); }
 
     FOR_EACH_SIMPLE_BUILTIN_TYPE(DEFINE_ACCESSORS_FOR_SIMPLE_TYPE)
-    FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(DEFINE_ACCESSORS_FOR_SIMPLE_TYPE)
 
 #undef DEFINE_ACCESSORS_FOR_SIMPLE_TYPE
 
+#define DEFINE_ACCESSORS_FOR_ITERATOR_TYPE(capitalName, lowerName, properName, instanceType, jsName) \
+    Structure* properName ## Structure() { return m_ ## properName ## Structure.get(this); }
+
+    FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(DEFINE_ACCESSORS_FOR_ITERATOR_TYPE)
+
+#undef DEFINE_ACCESSORS_FOR_ITERATOR_TYPE
+
+#define DEFINE_ACCESSORS_FOR_LAZY_TYPE(capitalName, lowerName, properName, instanceType, jsName) \
+    Structure* properName ## Structure() { return m_ ## properName ## Structure.get(this); }
+
+    FOR_EACH_LAZY_BUILTIN_TYPE(DEFINE_ACCESSORS_FOR_LAZY_TYPE)
+
+#undef DEFINE_ACCESSORS_FOR_LAZY_TYPE
+
+    LazyClassStructure& lazyTypedArrayStructure(TypedArrayType type)
+    {
+        switch (type) {
+        case NotTypedArray:
+            RELEASE_ASSERT_NOT_REACHED();
+            return m_typedArrayInt8;
+#define TYPED_ARRAY_TYPE_CASE(name) case Type ## name: return m_typedArray ## name;
+            FOR_EACH_TYPED_ARRAY_TYPE(TYPED_ARRAY_TYPE_CASE)
+#undef TYPED_ARRAY_TYPE_CASE
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return m_typedArrayInt8;
+    }
+    const LazyClassStructure& lazyTypedArrayStructure(TypedArrayType type) const
+    {
+        return const_cast<const LazyClassStructure&>(const_cast<JSGlobalObject*>(this)->lazyTypedArrayStructure(type));
+    }
+    
     Structure* typedArrayStructure(TypedArrayType type) const
     {
-        return m_typedArrays[toIndex(type)].structure.get();
+        return lazyTypedArrayStructure(type).get(this);
+    }
+    Structure* typedArrayStructureConcurrently(TypedArrayType type) const
+    {
+        return lazyTypedArrayStructure(type).getConcurrently();
     }
     bool isOriginalTypedArrayStructure(Structure* structure)
     {
         TypedArrayType type = structure->classInfo()->typedArrayStorageType;
         if (type == NotTypedArray)
             return false;
-        return typedArrayStructure(type) == structure;
+        return typedArrayStructureConcurrently(type) == structure;
     }
 
     JSObject* typedArrayConstructor(TypedArrayType type) const
     {
-        return m_typedArrays[toIndex(type)].constructor.get();
+        return lazyTypedArrayStructure(type).constructor(this);
     }
 
     JSCell* actualPointerFor(Special::Pointer pointer)
@@ -745,9 +801,6 @@ private:
 
     JS_EXPORT_PRIVATE void init(VM&);
 
-    void createThrowTypeError(VM&);
-    void createThrowTypeErrorArgumentsAndCaller(VM&);
-
     JS_EXPORT_PRIVATE static void clearRareData(JSCell*);
 
     bool m_needsSiteSpecificQuirks { false };
index f11a865..6ffb095 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -68,7 +68,8 @@ JSNativeStdFunction* JSNativeStdFunction::create(VM& vm, JSGlobalObject* globalO
 {
     NativeExecutable* executable = lookUpOrCreateNativeExecutable(vm, runStdFunction, intrinsic, nativeConstructor, name);
     NativeStdFunctionCell* functionCell = NativeStdFunctionCell::create(vm, WTFMove(nativeStdFunction));
-    JSNativeStdFunction* function = new (NotNull, allocateCell<JSNativeStdFunction>(vm.heap)) JSNativeStdFunction(vm, globalObject, globalObject->nativeStdFunctionStructure());
+    Structure* structure = globalObject->nativeStdFunctionStructure();
+    JSNativeStdFunction* function = new (NotNull, allocateCell<JSNativeStdFunction>(vm.heap)) JSNativeStdFunction(vm, globalObject, structure);
     function->finishCreation(vm, executable, length, name, functionCell);
     return function;
 }
index 1ffe8d1..08b6c68 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012, 2016 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,6 +32,15 @@ namespace JSC {
 
 const ClassInfo JSWithScope::s_info = { "WithScope", &Base::s_info, 0, CREATE_METHOD_TABLE(JSWithScope) };
 
+JSWithScope* JSWithScope::create(
+    VM& vm, JSGlobalObject* globalObject, JSObject* object, JSScope* next)
+{
+    Structure* structure = globalObject->withScopeStructure();
+    JSWithScope* withScope = new (NotNull, allocateCell<JSWithScope>(vm.heap)) JSWithScope(vm, structure, object, next);
+    withScope->finishCreation(vm);
+    return withScope;
+}
+
 void JSWithScope::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     JSWithScope* thisObject = jsCast<JSWithScope*>(cell);
@@ -40,4 +49,15 @@ void JSWithScope::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_object);
 }
 
+Structure* JSWithScope::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
+{
+    return Structure::create(vm, globalObject, proto, TypeInfo(WithScopeType, StructureFlags), info());
+}
+
+JSWithScope::JSWithScope(VM& vm, Structure* structure, JSObject* object, JSScope* next)
+    : Base(vm, structure, next)
+    , m_object(vm, this, object)
+{
+}
+
 } // namespace JSC
index 8e5d09f..1f297e3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012, 2016 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,34 +34,18 @@ class JSWithScope : public JSScope {
 public:
     typedef JSScope Base;
 
-    static JSWithScope* create(ExecState* exec, JSObject* object, JSScope* next)
-    {
-        JSWithScope* withScope = new (NotNull, allocateCell<JSWithScope>(*exec->heap())) JSWithScope(exec, object, next);
-        withScope->finishCreation(exec->vm());
-        return withScope;
-    }
+    JS_EXPORT_PRIVATE static JSWithScope* create(VM&, JSGlobalObject*, JSObject*, JSScope* next);
 
     JSObject* object() { return m_object.get(); }
 
     static void visitChildren(JSCell*, SlotVisitor&);
 
-    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
-    {
-        return Structure::create(vm, globalObject, proto, TypeInfo(WithScopeType, StructureFlags), info());
-    }
+    static Structure* createStructure(VM&, JSGlobalObject*, JSValue proto);
 
     DECLARE_EXPORT_INFO;
 
 private:
-    JSWithScope(ExecState* exec, JSObject* object, JSScope* next)
-        : Base(
-            exec->vm(),
-            exec->lexicalGlobalObject()->withScopeStructure(),
-            next
-        )
-        , m_object(exec->vm(), this, object)
-    {
-    }
+    JSWithScope(VM&, Structure*, JSObject*, JSScope* next);
 
     WriteBarrier<JSObject> m_object;
 };
diff --git a/Source/JavaScriptCore/runtime/LazyClassStructure.cpp b/Source/JavaScriptCore/runtime/LazyClassStructure.cpp
new file mode 100644 (file)
index 0000000..dbaf833
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LazyClassStructure.h"
+
+#include "JSCInlines.h"
+#include "LazyPropertyInlines.h"
+
+namespace JSC {
+
+LazyClassStructure::Initializer::Initializer(VM& vm, JSGlobalObject* global, LazyClassStructure& classStructure, const StructureInitializer& structureInit)
+    : vm(vm)
+    , global(global)
+    , classStructure(classStructure)
+    , structureInit(structureInit)
+{
+}
+
+void LazyClassStructure::Initializer::setPrototype(JSObject* prototype)
+{
+    RELEASE_ASSERT(!this->prototype);
+    RELEASE_ASSERT(!structure);
+    RELEASE_ASSERT(!constructor);
+    
+    this->prototype = prototype;
+}
+
+void LazyClassStructure::Initializer::setStructure(Structure* structure)
+{
+    RELEASE_ASSERT(!this->structure);
+    RELEASE_ASSERT(!constructor);
+
+    this->structure = structure;
+    structureInit.set(structure);
+    
+    if (!prototype)
+        prototype = structure->storedPrototypeObject();
+}
+
+void LazyClassStructure::Initializer::setConstructor(PropertyName propertyName, JSObject* constructor)
+{
+    RELEASE_ASSERT(structure);
+    RELEASE_ASSERT(prototype);
+    RELEASE_ASSERT(!this->constructor);
+    
+    this->constructor = constructor;
+
+    prototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, constructor, DontEnum);
+    if (!propertyName.isNull())
+        global->putDirect(vm, propertyName, constructor, DontEnum);
+    classStructure.m_constructor.set(vm, global, constructor);
+}
+
+void LazyClassStructure::Initializer::setConstructor(JSObject* constructor)
+{
+    String name;
+    if (InternalFunction* internalFunction = jsDynamicCast<InternalFunction*>(constructor))
+        name = internalFunction->name();
+    else if (JSFunction* function = jsDynamicCast<JSFunction*>(constructor))
+        name = function->name();
+    else
+        RELEASE_ASSERT_NOT_REACHED();
+    
+    setConstructor(Identifier::fromString(&vm, name), constructor);
+}
+
+void LazyClassStructure::visit(SlotVisitor& visitor)
+{
+    m_structure.visit(visitor);
+    visitor.append(&m_constructor);
+}
+
+void LazyClassStructure::dump(PrintStream& out) const
+{
+    out.print("<structure = ", m_structure, ", constructor = ", RawPointer(m_constructor.get()), ">");
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/runtime/LazyClassStructure.h b/Source/JavaScriptCore/runtime/LazyClassStructure.h
new file mode 100644 (file)
index 0000000..a5e6188
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LazyClassStructure_h
+#define LazyClassStructure_h
+
+#include "LazyProperty.h"
+#include "Structure.h"
+
+namespace JSC {
+
+class JSGlobalObject;
+class VM;
+
+class LazyClassStructure {
+    typedef LazyProperty<JSGlobalObject, Structure>::Initializer StructureInitializer;
+    
+public:
+    struct Initializer {
+        Initializer(VM&, JSGlobalObject*, LazyClassStructure&, const StructureInitializer&);
+        
+        // This should be called first or not at all.
+        void setPrototype(JSObject* prototype);
+        
+        // If this is called after setPrototype() then it just sets the structure. If this is
+        // called first then it sets the prototype by extracting it from the structure.
+        void setStructure(Structure*);
+        
+        // Call this last. It's expected that the constructor is initialized to point to the
+        // prototype already. This will automatically set prototype.constructor=constructor.
+        // This will also stuff the constructor into the global object at the given property.
+        // Note that the variant that does not take a property name attempts to deduce it by
+        // casting constructor to either JSFunction or InternalFunction. Also, you can pass
+        // nullptr for the property name, in which case we don't assign the property to the
+        // global object.
+        void setConstructor(PropertyName, JSObject* constructor);
+        void setConstructor(JSObject* constructor);
+        
+        VM& vm;
+        JSGlobalObject* global;
+        LazyClassStructure& classStructure;
+        const StructureInitializer& structureInit;
+        
+        // It's expected that you set these using the set methods above.
+        JSObject* prototype { nullptr };
+        Structure* structure { nullptr };
+        JSObject* constructor { nullptr };
+    };
+    
+    LazyClassStructure()
+    {
+    }
+    
+    template<typename Callback>
+    void initLater(const Callback&);
+    
+    Structure* get(const JSGlobalObject* global) const
+    {
+        ASSERT(!isCompilationThread());
+        return m_structure.get(global);
+    }
+    
+    JSObject* prototype(const JSGlobalObject* global) const
+    {
+        ASSERT(!isCompilationThread());
+        return get(global)->storedPrototypeObject();
+    }
+
+    // Almost as an afterthought, we also support getting the original constructor. This turns
+    // out to be important for ES6 support.
+    JSObject* constructor(const JSGlobalObject* global) const
+    {
+        ASSERT(!isCompilationThread());
+        m_structure.get(global);
+        return m_constructor.get();
+    }
+    
+    Structure* getConcurrently() const
+    {
+        return m_structure.getConcurrently();
+    }
+    
+    JSObject* prototypeConcurrently() const
+    {
+        if (Structure* structure = getConcurrently())
+            return structure->storedPrototypeObject();
+        return nullptr;
+    }
+    
+    JSObject* constructorConcurrently() const
+    {
+        return m_constructor.get();
+    }
+    
+    void visit(SlotVisitor&);
+    
+    void dump(PrintStream&) const;
+
+private:
+    LazyProperty<JSGlobalObject, Structure> m_structure;
+    WriteBarrier<JSObject> m_constructor;
+};
+
+} // namespace JSC
+
+#endif // LazyClassStructure_h
+
diff --git a/Source/JavaScriptCore/runtime/LazyClassStructureInlines.h b/Source/JavaScriptCore/runtime/LazyClassStructureInlines.h
new file mode 100644 (file)
index 0000000..f4056d8
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LazyClassStructureInlines_h
+#define LazyClassStructureInlines_h
+
+#include "LazyClassStructure.h"
+#include "LazyPropertyInlines.h"
+
+namespace JSC {
+
+template<typename Callback>
+void LazyClassStructure::initLater(const Callback&)
+{
+    m_structure.initLater(
+        [] (const StructureInitializer& structureInit) {
+            ptrdiff_t offset = OBJECT_OFFSETOF(LazyClassStructure, m_structure);
+            LazyClassStructure* thisStructure = bitwise_cast<LazyClassStructure*>(
+                bitwise_cast<char*>(&structureInit.property) - offset);
+            Initializer init(structureInit.vm, structureInit.owner, *thisStructure, structureInit);
+            callStatelessLambda<void, Callback>(init);
+        });
+}
+
+} // namespace JSC
+
+#endif // LazyClassStructureInlines_h
+
diff --git a/Source/JavaScriptCore/runtime/LazyProperty.h b/Source/JavaScriptCore/runtime/LazyProperty.h
new file mode 100644 (file)
index 0000000..818b315
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LazyProperty_h
+#define LazyProperty_h
+
+#include "VM.h"
+
+namespace JSC {
+
+class JSCell;
+class SlotVisitor;
+class VM;
+
+// Note that if all you're doing is calling LazyProperty::get(), it's completely safe to bitcast
+// this LazyProperty<JSCell, JSCell>.
+template<typename OwnerType, typename ElementType>
+class LazyProperty {
+public:
+    struct Initializer {
+        Initializer(OwnerType* owner, LazyProperty& property)
+            : vm(*Heap::heap(owner)->vm())
+            , owner(owner)
+            , property(property)
+        {
+        }
+        
+        void set(ElementType* value) const;
+
+        VM& vm;
+        OwnerType* owner;
+        LazyProperty& property;
+    };
+
+private:
+    typedef ElementType* (*FuncType)(const Initializer&);
+
+public:
+    LazyProperty()
+    {
+    }
+
+    // Tell the property to run the given callback next time someone tries to get the value
+    // using get(). The passed callback must be stateless. For example:
+    //
+    //     property.initLater(
+    //         [] (const LazyProperty<Foo, Bar>::Initializer& init) {
+    //             init.set(...things...);
+    //         });
+    //
+    // This method is always inlineable and should always compile to a store of a constant
+    // pointer no matter how complicated the callback is.
+    template<typename Func>
+    void initLater(const Func&);
+
+    // This lazily initializes the property. Note that this gracefully supports recursive calls.
+    // If this gets called while the property is being initialized, it will simply return null.
+    ElementType* get(const OwnerType* owner) const
+    {
+        ASSERT(!isCompilationThread());
+        if (UNLIKELY(m_pointer & lazyTag)) {
+            FuncType func = *bitwise_cast<FuncType*>(m_pointer & ~(lazyTag | initializingTag));
+            return func(Initializer(const_cast<OwnerType*>(owner), *const_cast<LazyProperty*>(this)));
+        }
+        return bitwise_cast<ElementType*>(m_pointer);
+    }
+    
+    ElementType* getConcurrently() const
+    {
+        uintptr_t pointer = m_pointer;
+        if (pointer & lazyTag)
+            return nullptr;
+        return bitwise_cast<ElementType*>(pointer);
+    }
+    
+    void setMayBeNull(VM&, const OwnerType* owner, ElementType*);
+    void set(VM&, const OwnerType* owner, ElementType*);
+    
+    void visit(SlotVisitor&);
+    
+    void dump(PrintStream&) const;
+    
+private:
+    template<typename Func>
+    static ElementType* callFunc(const Initializer&);
+    
+    static const uintptr_t lazyTag = 1;
+    static const uintptr_t initializingTag = 2;
+    
+    uintptr_t m_pointer { 0 };
+};
+
+// It's valid to bitcast any LazyProperty to LazyCellProperty if you're just going to call get()
+// or getConcurrently().
+typedef LazyProperty<JSCell, JSCell> LazyCellProperty;
+
+} // namespace JSC
+
+#endif // LazyProperty_h
+
diff --git a/Source/JavaScriptCore/runtime/LazyPropertyInlines.h b/Source/JavaScriptCore/runtime/LazyPropertyInlines.h
new file mode 100644 (file)
index 0000000..a7f2ab0
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LazyPropertyInlines_h
+#define LazyPropertyInlines_h
+
+#include "Heap.h"
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+template<typename OwnerType, typename ElementType>
+void LazyProperty<OwnerType, ElementType>::Initializer::set(ElementType* value) const
+{
+    property.set(vm, owner, value);
+}
+
+template<typename OwnerType, typename ElementType>
+template<typename Func>
+void LazyProperty<OwnerType, ElementType>::initLater(const Func&)
+{
+    RELEASE_ASSERT(isStatelessLambda<Func>());
+    // Logically we just want to stuff the function pointer into m_pointer, but then we'd be sad
+    // because a function pointer is not guaranteed to be a multiple of anything. The tag bits
+    // may be used for things. We address this problem by indirecting through a global const
+    // variable. The "theFunc" variable is guaranteed to be native-aligned, i.e. at least a
+    // multiple of 4.
+    static const FuncType theFunc = callFunc<Func>;
+    m_pointer = lazyTag | bitwise_cast<uintptr_t>(&theFunc);
+}
+
+template<typename OwnerType, typename ElementType>
+void LazyProperty<OwnerType, ElementType>::setMayBeNull(VM& vm, const OwnerType* owner, ElementType* value)
+{
+    vm.heap.writeBarrier(owner, value);
+    m_pointer = bitwise_cast<uintptr_t>(value);
+    RELEASE_ASSERT(!(m_pointer & lazyTag));
+}
+
+template<typename OwnerType, typename ElementType>
+void LazyProperty<OwnerType, ElementType>::set(VM& vm, const OwnerType* owner, ElementType* value)
+{
+    RELEASE_ASSERT(value);
+    setMayBeNull(vm, owner, value);
+}
+
+template<typename OwnerType, typename ElementType>
+void LazyProperty<OwnerType, ElementType>::visit(SlotVisitor& visitor)
+{
+    if (m_pointer && !(m_pointer & lazyTag))
+        visitor.appendUnbarrieredReadOnlyPointer(bitwise_cast<ElementType*>(m_pointer));
+}
+
+template<typename OwnerType, typename ElementType>
+void LazyProperty<OwnerType, ElementType>::dump(PrintStream& out) const
+{
+    if (!m_pointer) {
+        out.print("<null>");
+        return;
+    }
+    if (m_pointer & lazyTag) {
+        out.print("Lazy:", RawPointer(bitwise_cast<void*>(m_pointer & ~lazyTag)));
+        if (m_pointer & initializingTag)
+            out.print("(Initializing)");
+        return;
+    }
+    out.print(RawPointer(bitwise_cast<void*>(m_pointer)));
+}
+
+template<typename OwnerType, typename ElementType>
+template<typename Func>
+ElementType* LazyProperty<OwnerType, ElementType>::callFunc(const Initializer& initializer)
+{
+    if (initializer.property.m_pointer & initializingTag)
+        return nullptr;
+    initializer.property.m_pointer |= initializingTag;
+    callStatelessLambda<void, Func>(initializer);
+    RELEASE_ASSERT(!(initializer.property.m_pointer & lazyTag));
+    RELEASE_ASSERT(!(initializer.property.m_pointer & initializingTag));
+    return bitwise_cast<ElementType*>(initializer.property.m_pointer);
+}
+
+} // namespace JSC
+
+#endif // LazyPropertyInlines_h
+
index dcee6ba..2e41ca1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2008, 2012, 2015 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008, 2012, 2015-2016 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -45,7 +45,7 @@ void reifyStaticAccessor(VM& vm, const HashTableValue& value, JSObject& thisObj,
 bool setUpStaticFunctionSlot(ExecState* exec, const HashTableValue* entry, JSObject* thisObj, PropertyName propertyName, PropertySlot& slot)
 {
     ASSERT(thisObj->globalObject());
-    ASSERT(entry->attributes() & BuiltinOrFunctionOrAccessor);
+    ASSERT(entry->attributes() & BuiltinOrFunctionOrAccessorOrLazyProperty);
     VM& vm = exec->vm();
     unsigned attributes;
     bool isAccessor = entry->attributes() & Accessor;
@@ -63,13 +63,25 @@ bool setUpStaticFunctionSlot(ExecState* exec, const HashTableValue* entry, JSObj
             thisObj->putDirectNativeFunction(
                 vm, thisObj->globalObject(), propertyName, entry->functionLength(),
                 entry->function(), entry->intrinsic(), attributesForStructure(entry->attributes()));
-        } else {
-            ASSERT(isAccessor);
+        } else if (isAccessor)
             reifyStaticAccessor(vm, *entry, *thisObj, propertyName);
-        }
+        else if (entry->attributes() & CellProperty) {
+            LazyCellProperty* property = bitwise_cast<LazyCellProperty*>(
+                bitwise_cast<char*>(thisObj) + entry->lazyCellPropertyOffset());
+            JSCell* result = property->get(thisObj);
+            thisObj->putDirect(vm, propertyName, result, attributesForStructure(entry->attributes()));
+        } else if (entry->attributes() & ClassStructure) {
+            LazyClassStructure* structure = bitwise_cast<LazyClassStructure*>(
+                bitwise_cast<char*>(thisObj) + entry->lazyClassStructureOffset());
+            structure->get(jsCast<JSGlobalObject*>(thisObj));
+        } else if (entry->attributes() & PropertyCallback) {
+            JSValue result = entry->lazyPropertyCallback()(vm, thisObj);
+            thisObj->putDirect(vm, propertyName, result, attributesForStructure(entry->attributes()));
+        } else
+            RELEASE_ASSERT_NOT_REACHED();
 
         offset = thisObj->getDirectOffset(vm, propertyName, attributes);
-        ASSERT(isValidOffset(offset));
+        RELEASE_ASSERT(isValidOffset(offset));
     }
 
     if (isAccessor)
index 8f0ac5a..af78abe 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2006, 2007, 2008, 2009, 2016 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -28,6 +28,7 @@
 #include "IdentifierInlines.h"
 #include "Intrinsic.h"
 #include "JSGlobalObject.h"
+#include "LazyProperty.h"
 #include "PropertySlot.h"
 #include "PutPropertySlot.h"
 #include "Reject.h"
@@ -45,6 +46,7 @@ struct CompactHashIndex {
 typedef PropertySlot::GetValueFunc GetFunction;
 typedef PutPropertySlot::PutValueFunc PutFunction;
 typedef FunctionExecutable* (*BuiltinGenerator)(VM&);
+typedef JSValue (*LazyPropertyCallback)(VM&, JSObject*);
 
 // Hash table generated by the create_hash_table script.
 struct HashTableValue {
@@ -74,8 +76,8 @@ struct HashTableValue {
     NativeFunction function() const { ASSERT(m_attributes & Function); return reinterpret_cast<NativeFunction>(m_values.value1); }
     unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast<unsigned char>(m_values.value2); }
 
-    GetFunction propertyGetter() const { ASSERT(!(m_attributes & BuiltinOrFunctionOrAccessorOrConstant)); return reinterpret_cast<GetFunction>(m_values.value1); }
-    PutFunction propertyPutter() const { ASSERT(!(m_attributes & BuiltinOrFunctionOrAccessorOrConstant)); return reinterpret_cast<PutFunction>(m_values.value2); }
+    GetFunction propertyGetter() const { ASSERT(!(m_attributes & BuiltinOrFunctionOrAccessorOrLazyPropertyOrConstant)); return reinterpret_cast<GetFunction>(m_values.value1); }
+    PutFunction propertyPutter() const { ASSERT(!(m_attributes & BuiltinOrFunctionOrAccessorOrLazyPropertyOrConstant)); return reinterpret_cast<PutFunction>(m_values.value2); }
 
     NativeFunction accessorGetter() const { ASSERT(m_attributes & Accessor); return reinterpret_cast<NativeFunction>(m_values.value1); }
     NativeFunction accessorSetter() const { ASSERT(m_attributes & Accessor); return reinterpret_cast<NativeFunction>(m_values.value2); }
@@ -85,6 +87,10 @@ struct HashTableValue {
     long long constantInteger() const { ASSERT(m_attributes & ConstantInteger); return m_values.constant; }
 
     intptr_t lexerValue() const { ASSERT(!m_attributes); return m_values.value1; }
+    
+    ptrdiff_t lazyCellPropertyOffset() const { ASSERT(m_attributes & CellProperty); return m_values.value1; }
+    ptrdiff_t lazyClassStructureOffset() const { ASSERT(m_attributes & ClassStructure); return m_values.value1; }
+    LazyPropertyCallback lazyPropertyCallback() const { ASSERT(m_attributes & PropertyCallback); return reinterpret_cast<LazyPropertyCallback>(m_values.value1); }
 };
 
 struct HashTable {
@@ -221,7 +227,7 @@ inline bool getStaticPropertySlot(ExecState* exec, const HashTable& table, ThisI
     if (!entry)
         return false;
 
-    if (entry->attributes() & BuiltinOrFunctionOrAccessor)
+    if (entry->attributes() & BuiltinOrFunctionOrAccessorOrLazyProperty)
         return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
 
     if (entry->attributes() & ConstantInteger) {
@@ -271,7 +277,7 @@ inline bool getStaticValueSlot(ExecState* exec, const HashTable& table, ThisImp*
     if (!entry)
         return false;
 
-    ASSERT(!(entry->attributes() & BuiltinOrFunctionOrAccessor));
+    ASSERT(!(entry->attributes() & BuiltinOrFunctionOrAccessorOrLazyProperty));
 
     if (entry->attributes() & ConstantInteger) {
         slot.setValue(thisObj, attributesForStructure(entry->attributes()), jsNumber(entry->constantInteger()));
@@ -287,9 +293,10 @@ inline bool getStaticValueSlot(ExecState* exec, const HashTable& table, ThisImp*
 // 'slot.thisValue()' is the object the put was originally performed on (in the case of a proxy, the proxy itself).
 inline bool putEntry(ExecState* exec, const HashTableValue* entry, JSObject* base, JSObject* thisValue, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
 {
-    if (entry->attributes() & BuiltinOrFunction) {
+    if (entry->attributes() & BuiltinOrFunctionOrLazyProperty) {
         if (!(entry->attributes() & ReadOnly)) {
-            // If this is a function put it as an override property.
+            // If this is a function or lazy property put then we just do the put because
+            // logically the object already had the property, so this is just a replace.
             if (JSObject* thisObject = jsDynamicCast<JSObject*>(thisValue))
                 thisObject->putDirect(exec->vm(), propertyName, value);
             return true;
@@ -360,6 +367,27 @@ inline void reifyStaticProperty(VM& vm, const HashTableValue& value, JSObject& t
         reifyStaticAccessor(vm, value, thisObj, propertyName);
         return;
     }
+    
+    if (value.attributes() & CellProperty) {
+        LazyCellProperty* property = bitwise_cast<LazyCellProperty*>(
+            bitwise_cast<char*>(&thisObj) + value.lazyCellPropertyOffset());
+        JSCell* result = property->get(&thisObj);
+        thisObj.putDirect(vm, propertyName, result, attributesForStructure(value.attributes()));
+        return;
+    }
+    
+    if (value.attributes() & ClassStructure) {
+        LazyClassStructure* structure = bitwise_cast<LazyClassStructure*>(
+            bitwise_cast<char*>(&thisObj) + value.lazyClassStructureOffset());
+        structure->get(jsCast<JSGlobalObject*>(&thisObj));
+        return;
+    }
+    
+    if (value.attributes() & PropertyCallback) {
+        JSValue result = value.lazyPropertyCallback()(vm, &thisObj);
+        thisObj.putDirect(vm, propertyName, result, attributesForStructure(value.attributes()));
+        return;
+    }
 
     CustomGetterSetter* customGetterSetter = CustomGetterSetter::create(vm, value.propertyGetter(), value.propertyPutter());
     thisObj.putDirectCustomAccessor(vm, propertyName, customGetterSetter, attributesForStructure(value.attributes()));
index d163a24..15403cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2005, 2007, 2008, 2015 Apple Inc. All rights reserved.
+ *  Copyright (C) 2005, 2007, 2008, 2015-2016 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -46,9 +46,13 @@ enum Attribute {
     Function          = 1 << 8,  // property is a function - only used by static hashtables
     Builtin           = 1 << 9,  // property is a builtin function - only used by static hashtables
     ConstantInteger   = 1 << 10, // property is a constant integer - only used by static hashtables
+    CellProperty      = 1 << 11, // property is a lazy property - only used by static hashtables
+    ClassStructure    = 1 << 12, // property is a lazy class structure - only used by static hashtables
+    PropertyCallback  = 1 << 13, // property that is a lazy property callback - only used by static hashtables
     BuiltinOrFunction = Builtin | Function, // helper only used by static hashtables
-    BuiltinOrFunctionOrAccessor = Builtin | Function | Accessor, // helper only used by static hashtables
-    BuiltinOrFunctionOrAccessorOrConstant = Builtin | Function | Accessor | ConstantInteger, // helper only used by static hashtables
+    BuiltinOrFunctionOrLazyProperty = Builtin | Function | CellProperty | ClassStructure | PropertyCallback, // helper only used by static hashtables
+    BuiltinOrFunctionOrAccessorOrLazyProperty = Builtin | Function | Accessor | CellProperty | ClassStructure | PropertyCallback, // helper only used by static hashtables
+    BuiltinOrFunctionOrAccessorOrLazyPropertyOrConstant = Builtin | Function | Accessor | CellProperty | ClassStructure | PropertyCallback | ConstantInteger // helper only used by static hashtables
 };
 
 enum CacheabilityType : uint8_t {
index 3a08eeb..f1969aa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,18 +33,34 @@ namespace JSC {
 
 struct ClassInfo;
 
+#define FOR_EACH_TYPED_ARRAY_TYPE(macro) \
+    macro(Int8) \
+    macro(Uint8) \
+    macro(Uint8Clamped) \
+    macro(Int16) \
+    macro(Uint16) \
+    macro(Int32) \
+    macro(Uint32) \
+    macro(Float32) \
+    macro(Float64) \
+    macro(DataView)
+
+#define FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(macro) \
+    macro(Int8) \
+    macro(Uint8) \
+    macro(Uint8Clamped) \
+    macro(Int16) \
+    macro(Uint16) \
+    macro(Int32) \
+    macro(Uint32) \
+    macro(Float32) \
+    macro(Float64)
+
 enum TypedArrayType {
     NotTypedArray,
-    TypeInt8,
-    TypeUint8,
-    TypeUint8Clamped,
-    TypeInt16,
-    TypeUint16,
-    TypeInt32,
-    TypeUint32,
-    TypeFloat32,
-    TypeFloat64,
-    TypeDataView
+#define DECLARE_TYPED_ARRAY_TYPE(name) Type ## name,
+    FOR_EACH_TYPED_ARRAY_TYPE(DECLARE_TYPED_ARRAY_TYPE)
+#undef DECLARE_TYPED_ARRAY_TYPE
 };
 
 #define NUMBER_OF_TYPED_ARRAY_TYPES TypeDataView
index 893b7da..bc5f530 100644 (file)
@@ -1,3 +1,49 @@
+2016-05-04  Filip Pizlo  <fpizlo@apple.com>
+
+        Speed up JSGlobalObject initialization by making some properties lazy
+        https://bugs.webkit.org/show_bug.cgi?id=157045
+
+        Reviewed by Keith Miller.
+        
+        This WTF change is at the heart of a large JSC change. In JSC I found myself wanting to
+        do this a lot:
+        
+            static void callback(Foo& foo) { ... }
+        
+            foo.setCallback(callback);
+        
+        But that's not very nice to write if many different setCallback() calls are inside of the
+        same very large function: you'll have to have a lot of static function definitions in
+        one part of the file, and then a bunch of setCallback() calls in another part. It's hard
+        to reason about what's going on with such code.
+        
+        So what if you wrote this instead:
+        
+            foo.setCallback([] (Foo& foo) { ... });
+        
+        Much nicer! There is a standard way to do this: lambdas that are stateless are
+        convertible to function pointers. This change also offers another approach that is a bit
+        more general.
+        
+        These additions to WTF help you do it:
+        
+        isStatelessLambda<Func>(): tells you if Func is a stateless lambda. This uses is_empty to
+        test if the lambda is stateless. This turns out to be a stronger property than
+        convertibility to function pointers. For example, a function pointer is convertible to a
+        function pointer, but it is definitely stateful: you cannot successfully call it if you
+        only has its type. On the other hand, a stateless lambda is really stateless in the sense
+        that you only need its type to call it.
+        
+        callStatelessLambda<ResultType, Func>(Arguments&&...): calls the given stateless lambda.
+        
+        JSC uses these to build up some sophisticated lazy-initialization APIs. The use of
+        statelessness allows JSC to combine a lambda with other logic into a single function
+        pointer.
+
+        * wtf/StdLibExtras.h:
+        (WTF::isStatelessLambda):
+        (WTF::callStatelessLambda):
+
 2016-05-04  Per Arne Vollan  <peavo@outlook.com>
 
         [Win] Use NeverDestroyed template.
index eaa1a8f..9eb373b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2016 Apple Inc. All Rights Reserved.
  * Copyright (C) 2013 Patrick Gansterer <paroga@paroga.com>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,7 @@
 
 #include <chrono>
 #include <memory>
+#include <string.h>
 #include <wtf/Assertions.h>
 #include <wtf/CheckedArithmetic.h>
 
@@ -284,6 +285,20 @@ inline void insertIntoBoundedVector(VectorType& vector, size_t size, const Eleme
 // https://bugs.webkit.org/show_bug.cgi?id=131815
 WTF_EXPORT_PRIVATE bool isCompilationThread();
 
+template<typename Func>
+bool isStatelessLambda()
+{
+    return std::is_empty<Func>::value;
+}
+
+template<typename ResultType, typename Func, typename... ArgumentTypes>
+ResultType callStatelessLambda(ArgumentTypes&&... arguments)
+{
+    uint64_t data[(sizeof(Func) + sizeof(uint64_t) - 1) / sizeof(uint64_t)];
+    memset(data, 0, sizeof(data));
+    return (*bitwise_cast<Func*>(data))(std::forward<ArgumentTypes>(arguments)...);
+}
+
 } // namespace WTF
 
 // This version of placement new omits a 0 check.
@@ -403,6 +418,8 @@ using WTF::tryBinarySearch;
 using WTF::approximateBinarySearch;
 using WTF::bitwise_cast;
 using WTF::safeCast;
+using WTF::isStatelessLambda;
+using WTF::callStatelessLambda;
 
 #if COMPILER_SUPPORTS(CXX_USER_LITERALS)
 // We normally don't want to bring in entire std namespaces, but literals are an exception.
index deaba9a..08d6fbf 100644 (file)
@@ -1,3 +1,20 @@
+2016-05-04  Filip Pizlo  <fpizlo@apple.com>
+
+        Speed up JSGlobalObject initialization by making some properties lazy
+        https://bugs.webkit.org/show_bug.cgi?id=157045
+
+        Reviewed by Keith Miller.
+
+        No new tests because no change in behavior.
+        
+        This adapts JSHTMLElementCustom.cpp to the new JSWithScope API. Note that this revealed
+        that this was using a curious choice of global object, which may not be right. I decided
+        to do a very literal refactoring that exactly preserves what this code got before, but I
+        added a FIXME to reconsider this later.
+
+        * bindings/js/JSHTMLElementCustom.cpp:
+        (WebCore::JSHTMLElement::pushEventHandlerScope):
+
 2016-05-04  Manuel Rego Casasnovas  <rego@igalia.com>
 
         [css-grid] Refactor information stored related to column positions
index a2b3e1d..693fb1d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -101,14 +101,21 @@ JSScope* JSHTMLElement::pushEventHandlerScope(ExecState* exec, JSScope* scope) c
     HTMLElement& element = wrapped();
 
     // The document is put on first, fall back to searching it only after the element and form.
-    scope = JSWithScope::create(exec, asObject(toJS(exec, globalObject(), &element.document())), scope);
+    // FIXME: This probably may use the wrong global object. If this is called from a native
+    // function, then it would be correct but not optimal since the native function would *know*
+    // the global object. But, it may be that globalObject() is more correct.
+    // https://bugs.webkit.org/show_bug.cgi?id=134932
+    VM& vm = exec->vm();
+    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
+    
+    scope = JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), &element.document())), scope);
 
     // The form is next, searched before the document, but after the element itself.
     if (HTMLFormElement* form = element.form())
-        scope = JSWithScope::create(exec, asObject(toJS(exec, globalObject(), form)), scope);
+        scope = JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), form)), scope);
 
     // The element is on top, searched first.
-    return JSWithScope::create(exec, asObject(toJS(exec, globalObject(), &element)), scope);
+    return JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), &element)), scope);
 }
 
 } // namespace WebCore