Ignore:
Timestamp:
Jan 11, 2016, 1:31:04 PM (10 years ago)
Author:
[email protected]
Message:

Use a profile to store allocation structures for subclasses of InternalFunctions
https://bugs.webkit.org/show_bug.cgi?id=152942

Reviewed by Michael Saboff.

This patch adds InternalFunctionAllocationProfile to FunctionRareData, which holds
a cached structure that can be used to quickly allocate any derived class of an InternalFunction.
InternalFunctionAllocationProfile ended up being distinct from ObjectAllocationProfile, due to
constraints imposed by Reflect.construct. Reflect.construct allows the user to pass an arbitrary
constructor as a new.target to any other constructor. This means that a user can pass some
non-derived constructor to an InternalFunction (they can even pass another InternalFunction as the
new.target). If we use the same profile for both InternalFunctions and JS allocations then we always
need to check in both JS code and C++ code that the profiled structure has the same ClassInfo as the
current constructor. By using different profiles, we only need to check the profile in InternalFunctions
as all JS constructed objects share the same ClassInfo (JSFinalObject). This comes at the relatively
low cost of using slightly more memory on FunctionRareData and being slightly more conceptually complex.

Additionally, this patch adds subclassing to some omitted classes.

  • API/JSObjectRef.cpp:

(JSObjectMakeDate):
(JSObjectMakeRegExp):

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/InternalFunctionAllocationProfile.h: Added.

(JSC::InternalFunctionAllocationProfile::structure):
(JSC::InternalFunctionAllocationProfile::clear):
(JSC::InternalFunctionAllocationProfile::visitAggregate):
(JSC::InternalFunctionAllocationProfile::createAllocationStructureFromBase):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGOperations.cpp:
  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_create_this):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_create_this):

  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/BooleanConstructor.cpp:

(JSC::constructWithBooleanConstructor):

  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/DateConstructor.cpp:

(JSC::constructDate):
(JSC::constructWithDateConstructor):

  • runtime/DateConstructor.h:
  • runtime/ErrorConstructor.cpp:

(JSC::Interpreter::constructWithErrorConstructor):

  • runtime/FunctionRareData.cpp:

(JSC::FunctionRareData::create):
(JSC::FunctionRareData::visitChildren):
(JSC::FunctionRareData::FunctionRareData):
(JSC::FunctionRareData::initializeObjectAllocationProfile):
(JSC::FunctionRareData::clear):
(JSC::FunctionRareData::finishCreation): Deleted.
(JSC::FunctionRareData::initialize): Deleted.

  • runtime/FunctionRareData.h:

(JSC::FunctionRareData::offsetOfObjectAllocationProfile):
(JSC::FunctionRareData::objectAllocationProfile):
(JSC::FunctionRareData::objectAllocationStructure):
(JSC::FunctionRareData::allocationProfileWatchpointSet):
(JSC::FunctionRareData::isObjectAllocationProfileInitialized):
(JSC::FunctionRareData::internalFunctionAllocationStructure):
(JSC::FunctionRareData::createInternalFunctionAllocationStructureFromBase):
(JSC::FunctionRareData::offsetOfAllocationProfile): Deleted.
(JSC::FunctionRareData::allocationProfile): Deleted.
(JSC::FunctionRareData::allocationStructure): Deleted.
(JSC::FunctionRareData::isInitialized): Deleted.

  • runtime/InternalFunction.cpp:

(JSC::InternalFunction::createSubclassStructure):

  • runtime/InternalFunction.h:
  • runtime/JSArrayBufferConstructor.cpp:

(JSC::constructArrayBuffer):

  • runtime/JSFunction.cpp:

(JSC::JSFunction::allocateRareData):
(JSC::JSFunction::allocateAndInitializeRareData):
(JSC::JSFunction::initializeRareData):

  • runtime/JSFunction.h:

(JSC::JSFunction::rareData):

  • runtime/JSGenericTypedArrayViewConstructorInlines.h:

(JSC::constructGenericTypedArrayView):

  • runtime/JSObject.h:

(JSC::JSFinalObject::typeInfo):
(JSC::JSFinalObject::createStructure):

  • runtime/JSPromiseConstructor.cpp:

(JSC::constructPromise):

  • runtime/JSPromiseConstructor.h:
  • runtime/JSWeakMap.cpp:
  • runtime/JSWeakSet.cpp:
  • runtime/MapConstructor.cpp:

(JSC::constructMap):

  • runtime/NativeErrorConstructor.cpp:

(JSC::Interpreter::constructWithNativeErrorConstructor):

  • runtime/NumberConstructor.cpp:

(JSC::constructWithNumberConstructor):

  • runtime/PrototypeMap.cpp:

(JSC::PrototypeMap::createEmptyStructure):
(JSC::PrototypeMap::emptyStructureForPrototypeFromBaseStructure):
(JSC::PrototypeMap::emptyObjectStructureForPrototype):
(JSC::PrototypeMap::clearEmptyObjectStructureForPrototype):

  • runtime/PrototypeMap.h:
  • runtime/RegExpConstructor.cpp:

(JSC::getRegExpStructure):
(JSC::constructRegExp):
(JSC::constructWithRegExpConstructor):

  • runtime/RegExpConstructor.h:
  • runtime/SetConstructor.cpp:

(JSC::constructSet):

  • runtime/WeakMapConstructor.cpp:

(JSC::constructWeakMap):

  • runtime/WeakSetConstructor.cpp:

(JSC::constructWeakSet):

  • tests/stress/class-subclassing-misc.js:

(A):
(D):
(E):
(WM):
(WS):
(test):

  • tests/stress/class-subclassing-typedarray.js: Added.

(test):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/InternalFunction.cpp

    r171824 r194863  
    22 *  Copyright (C) 1999-2002 Harri Porten ([email protected])
    33 *  Copyright (C) 2001 Peter Kelly ([email protected])
    4  *  Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
     4 *  Copyright (C) 2004, 2007, 2008, 2016 Apple Inc. All rights reserved.
    55 *
    66 *  This library is free software; you can redistribute it and/or
     
    7979}
    8080
     81Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue newTarget, Structure* baseClass)
     82{
     83
     84    VM& vm = exec->vm();
     85    // We allow newTarget == JSValue() because the API needs to be able to create classes without having a real JS frame.
     86    // Since we don't allow subclassing in the API we just treat newTarget == JSValue() as newTarget == exec->callee()
     87    ASSERT(!newTarget || newTarget.isFunction());
     88
     89    if (newTarget && newTarget != exec->callee()) {
     90        // newTarget may be an InternalFunction if we were called from Reflect.construct.
     91        JSFunction* targetFunction = jsDynamicCast<JSFunction*>(newTarget);
     92
     93        if (LIKELY(targetFunction)) {
     94            Structure* structure = targetFunction->rareData(vm)->internalFunctionAllocationStructure();
     95            if (LIKELY(structure && structure->classInfo() == baseClass->classInfo()))
     96                return structure;
     97
     98            // Note, Reflect.construct might cause the profile to churn but we don't care.
     99            JSObject* prototype = jsDynamicCast<JSObject*>(newTarget.get(exec, exec->propertyNames().prototype));
     100            if (prototype)
     101                return targetFunction->rareData(vm)->createInternalFunctionAllocationStructureFromBase(vm, prototype, baseClass);
     102        } else {
     103            JSObject* prototype = jsDynamicCast<JSObject*>(newTarget.get(exec, exec->propertyNames().prototype));
     104            if (prototype) {
     105                // This only happens if someone Reflect.constructs our builtin constructor with another builtin constructor as the new.target.
     106                // Thus, we don't care about the cost of looking up the structure from our hash table every time.
     107                return vm.prototypeMap.emptyStructureForPrototypeFromBaseStructure(prototype, baseClass);
     108            }
     109        }
     110    }
     111   
     112    return baseClass;
     113}
     114
     115
    81116} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.