Changeset 116670 in webkit


Ignore:
Timestamp:
May 10, 2012 11:40:29 AM (12 years ago)
Author:
barraclough@apple.com
Message:

Cache inheritorID on JSFunction
https://bugs.webkit.org/show_bug.cgi?id=85853

Reviewed by Geoff Garen & Filip Pizlo.

An object's prototype is indicated via its structure. To create an otherwise
empty object with object A as its prototype, we require a structure with its
prototype set to point to A. We wish to use this same structure for all empty
objects created with a prototype of A, so we presently store this structure as
a property of A, known as the inheritorID.

When a function F is invoked as a constructor, where F has a property 'prototype'
set to point to A, in order to create the 'this' value for the constructor to
use the following steps are taken:

  • the 'prototype' proptery of F is read, via a regular Get? access.
  • the inheritorID internal property of the prototype is read.
  • a new, empty object is constructed with its structure set to point to inheritorID.

There are two drawbacks to the current approach:

  • it requires that every object has an inheritorID field.
  • it requires a Get? access on every constructor call to access the 'prototype' property.

Instead, switch to caching a copy of the inheritorID on the function. Constructor
calls now only need read the internal property from the callee, saving a Get?.
This also means that JSObject::m_inheritorID is no longer commonly read, and in a
future patch we can move to storing this in a more memory efficient fashion.

(JSC::CodeBlock::dump):

  • bytecode/Opcode.h:

(JSC):
(JSC::padOpcodeName):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):

  • dfg/DFGAbstractState.cpp:

(JSC::DFG::AbstractState::execute):

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGNodeType.h:

(DFG):

  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::privateExecute):

  • jit/JITInlineMethods.h:

(JSC::JIT::emitAllocateJSFunction):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_create_this):
(JSC::JIT::emitSlow_op_create_this):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_create_this):
(JSC::JIT::emitSlow_op_create_this):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

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

(JSC::JSFunction::JSFunction):
(JSC::JSFunction::cacheInheritorID):
(JSC):
(JSC::JSFunction::put):
(JSC::JSFunction::defineOwnProperty):

  • runtime/JSFunction.h:

(JSC::JSFunction::cachedInheritorID):
(JSFunction):
(JSC::JSFunction::offsetOfCachedInheritorID):

Location:
trunk/Source/JavaScriptCore
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r116659 r116670  
     12012-05-10  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Cache inheritorID on JSFunction
     4        https://bugs.webkit.org/show_bug.cgi?id=85853
     5
     6        Reviewed by Geoff Garen & Filip Pizlo.
     7
     8        An object's prototype is indicated via its structure.  To create an otherwise
     9        empty object with object A as its prototype, we require a structure with its
     10        prototype set to point to A.  We wish to use this same structure for all empty
     11        objects created with a prototype of A, so we presently store this structure as
     12        a property of A, known as the inheritorID.
     13
     14        When a function F is invoked as a constructor, where F has a property 'prototype'
     15        set to point to A, in order to create the 'this' value for the constructor to
     16        use the following steps are taken:
     17          - the 'prototype' proptery of F is read, via a regular [[Get]] access.
     18          - the inheritorID internal property of the prototype is read.
     19          - a new, empty object is constructed with its structure set to point to inheritorID.
     20
     21        There are two drawbacks to the current approach:
     22          - it requires that every object has an inheritorID field.
     23          - it requires a [[Get]] access on every constructor call to access the 'prototype' property.
     24
     25        Instead, switch to caching a copy of the inheritorID on the function.  Constructor
     26        calls now only need read the internal property from the callee, saving a [[Get]].
     27        This also means that JSObject::m_inheritorID is no longer commonly read, and in a
     28        future patch we can move to storing this in a more memory efficient fashion.
     29
     30        * JavaScriptCore.xcodeproj/project.pbxproj:
     31        * bytecode/CodeBlock.cpp:
     32        (JSC::CodeBlock::dump):
     33        * bytecode/Opcode.h:
     34        (JSC):
     35        (JSC::padOpcodeName):
     36        * bytecompiler/BytecodeGenerator.cpp:
     37        (JSC::BytecodeGenerator::BytecodeGenerator):
     38        * dfg/DFGAbstractState.cpp:
     39        (JSC::DFG::AbstractState::execute):
     40        * dfg/DFGByteCodeParser.cpp:
     41        (JSC::DFG::ByteCodeParser::parseBlock):
     42        * dfg/DFGNodeType.h:
     43        (DFG):
     44        * dfg/DFGOperations.cpp:
     45        * dfg/DFGOperations.h:
     46        * dfg/DFGPredictionPropagationPhase.cpp:
     47        (JSC::DFG::PredictionPropagationPhase::propagate):
     48        * dfg/DFGSpeculativeJIT32_64.cpp:
     49        (JSC::DFG::SpeculativeJIT::compile):
     50        * dfg/DFGSpeculativeJIT64.cpp:
     51        (JSC::DFG::SpeculativeJIT::compile):
     52        * interpreter/Interpreter.cpp:
     53        (JSC::Interpreter::privateExecute):
     54        * jit/JITInlineMethods.h:
     55        (JSC::JIT::emitAllocateJSFunction):
     56        * jit/JITOpcodes.cpp:
     57        (JSC::JIT::emit_op_create_this):
     58        (JSC::JIT::emitSlow_op_create_this):
     59        * jit/JITOpcodes32_64.cpp:
     60        (JSC::JIT::emit_op_create_this):
     61        (JSC::JIT::emitSlow_op_create_this):
     62        * jit/JITStubs.cpp:
     63        (JSC::DEFINE_STUB_FUNCTION):
     64        * llint/LLIntSlowPaths.cpp:
     65        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     66        * llint/LowLevelInterpreter32_64.asm:
     67        * llint/LowLevelInterpreter64.asm:
     68        * runtime/JSFunction.cpp:
     69        (JSC::JSFunction::JSFunction):
     70        (JSC::JSFunction::cacheInheritorID):
     71        (JSC):
     72        (JSC::JSFunction::put):
     73        (JSC::JSFunction::defineOwnProperty):
     74        * runtime/JSFunction.h:
     75        (JSC::JSFunction::cachedInheritorID):
     76        (JSFunction):
     77        (JSC::JSFunction::offsetOfCachedInheritorID):
     78
    1792012-05-10  Michael Saboff  <msaboff@apple.com>
    280
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r115590 r116670  
    10421042                869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedTranscendentalFunction.h; sourceTree = "<group>"; };
    10431043                869EBCB60E8C6D4A008722CC /* ResultType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultType.h; sourceTree = "<group>"; };
     1044                86A054461556451B00445157 /* LowLevelInterpreter.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = LowLevelInterpreter.asm; path = llint/LowLevelInterpreter.asm; sourceTree = "<group>"; };
     1045                86A054471556451B00445157 /* LowLevelInterpreter32_64.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = LowLevelInterpreter32_64.asm; path = llint/LowLevelInterpreter32_64.asm; sourceTree = "<group>"; };
     1046                86A054481556451B00445157 /* LowLevelInterpreter64.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = LowLevelInterpreter64.asm; path = llint/LowLevelInterpreter64.asm; sourceTree = "<group>"; };
    10441047                86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic.cpp; sourceTree = "<group>"; };
    10451048                86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMv7Assembler.h; sourceTree = "<group>"; };
     
    14311434                                A767FF9F14F4502900789059 /* JSCTypedArrayStubs.h */,
    14321435                                F68EBB8C0255D4C601FF60F7 /* config.h */,
    1433                                 0F46809C14BA7F4D00BFE272 /* llint */,
    14341436                                1432EBD70A34CAD400717B9F /* API */,
    14351437                                9688CB120ED12B4E001D649F /* assembler */,
     
    14411443                                1429D77A0ED20D7300B89619 /* interpreter */,
    14421444                                1429D92C0ED22D7000B89619 /* jit */,
     1445                                0F46809C14BA7F4D00BFE272 /* llint */,
    14431446                                7E39D8370EC3A388003AF11A /* parser */,
    14441447                                95AB831A0DA42C6900BC83F3 /* profiler */,
     
    14901493                                0F4680A014BA7F8200BFE272 /* LLIntSlowPaths.h */,
    14911494                                0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */,
     1495                                86A054461556451B00445157 /* LowLevelInterpreter.asm */,
     1496                                86A054471556451B00445157 /* LowLevelInterpreter32_64.asm */,
     1497                                86A054481556451B00445157 /* LowLevelInterpreter64.asm */,
    14921498                        );
    14931499                        name = llint;
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r113648 r116670  
    520520        case op_create_this: {
    521521            int r0 = (++it)->u.operand;
    522             int r1 = (++it)->u.operand;
    523             dataLog("[%4d] create_this %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
     522            dataLog("[%4d] create_this %s\n", location, registerName(exec, r0).data());
    524523            break;
    525524        }
  • trunk/Source/JavaScriptCore/bytecode/Opcode.h

    r113136 r116670  
    4343        macro(op_init_lazy_reg, 2) \
    4444        macro(op_create_arguments, 2) \
    45         macro(op_create_this, 3) \
     45        macro(op_create_this, 2) \
    4646        macro(op_get_callee, 2) \
    4747        macro(op_convert_this, 2) \
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r113363 r116670  
    443443
    444444    if (isConstructor()) {
    445         RefPtr<RegisterID> func = newTemporary();
    446         RefPtr<RegisterID> funcProto = newTemporary();
    447 
    448         emitOpcode(op_get_callee);
    449         instructions().append(func->index());
    450         // Load prototype.
    451         emitGetById(funcProto.get(), func.get(), globalData()->propertyNames->prototype);
    452 
    453445        emitOpcode(op_create_this);
    454446        instructions().append(m_thisRegister.index());
    455         instructions().append(funcProto->index());
    456447    } else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) {
    457448        emitOpcode(op_convert_this);
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp

    r115248 r116670  
    775775        break;
    776776    }
    777            
     777
    778778    case CreateThis: {
    779         Node& child = m_graph[node.child1()];
    780779        AbstractValue& source = forNode(node.child1());
    781780        AbstractValue& destination = forNode(nodeIndex);
    782781           
    783         if (child.shouldSpeculateFinalObject())
    784             source.filter(PredictFinalObject);
    785            
     782        source.filter(PredictFunction);
    786783        destination.set(PredictFinalObject);
    787784        break;
    788785    }
    789            
     786
    790787    case NewObject:
    791788        forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->emptyObjectStructure());
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r116168 r116670  
    15351535
    15361536        case op_create_this: {
    1537             NodeIndex op1 = get(currentInstruction[2].u.operand);
    1538             set(currentInstruction[1].u.operand, addToGraph(CreateThis, op1));
     1537            if (m_inlineStackTop->m_inlineCallFrame)
     1538                set(currentInstruction[1].u.operand, addToGraph(CreateThis, getDirect(m_inlineStackTop->m_calleeVR)));
     1539            else
     1540                set(currentInstruction[1].u.operand, addToGraph(CreateThis, addToGraph(GetCallee)));
    15391541            NEXT_OPCODE(op_create_this);
    15401542        }
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r115867 r116670  
    210210}
    211211
    212 inline JSCell* createThis(ExecState* exec, JSCell* prototype, JSFunction* constructor)
    213 {
     212JSCell* DFG_OPERATION operationCreateThis(ExecState* exec, JSCell* constructor)
     213{
     214    JSGlobalData* globalData = &exec->globalData();
     215    NativeCallFrameTracer tracer(globalData, exec);
     216
    214217#if !ASSERT_DISABLED
    215218    ConstructData constructData;
    216     ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
     219    ASSERT(jsCast<JSFunction*>(constructor)->methodTable()->getConstructData(jsCast<JSFunction*>(constructor), constructData) == ConstructTypeJS);
    217220#endif
    218221   
    219     JSGlobalData& globalData = exec->globalData();
    220     NativeCallFrameTracer tracer(&globalData, exec);
    221 
    222     Structure* structure;
    223     if (prototype->isObject())
    224         structure = asObject(prototype)->inheritorID(globalData);
    225     else
    226         structure = constructor->scope()->globalObject->emptyObjectStructure();
    227    
    228     return constructEmptyObject(exec, structure);
    229 }
    230 
    231 JSCell* DFG_OPERATION operationCreateThis(ExecState* exec, JSCell* prototype)
    232 {
    233     JSGlobalData* globalData = &exec->globalData();
    234     NativeCallFrameTracer tracer(globalData, exec);
    235 
    236     return createThis(exec, prototype, jsCast<JSFunction*>(exec->callee()));
    237 }
    238 
    239 JSCell* DFG_OPERATION operationCreateThisInlined(ExecState* exec, JSCell* prototype, JSCell* constructor)
    240 {
    241     JSGlobalData* globalData = &exec->globalData();
    242     NativeCallFrameTracer tracer(globalData, exec);
    243    
    244     return createThis(exec, prototype, jsCast<JSFunction*>(constructor));
     222    return constructEmptyObject(exec, jsCast<JSFunction*>(constructor)->cachedInheritorID(exec));
    245223}
    246224
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r113930 r116670  
    9898// These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
    9999JSCell* DFG_OPERATION operationNewObject(ExecState*);
    100 JSCell* DFG_OPERATION operationCreateThis(ExecState*, JSCell* encodedOp1);
    101 JSCell* DFG_OPERATION operationCreateThisInlined(ExecState*, JSCell* encodedOp1, JSCell* constructor);
     100JSCell* DFG_OPERATION operationCreateThis(ExecState*, JSCell* constructor);
    102101EncodedJSValue DFG_OPERATION operationConvertThis(ExecState*, EncodedJSValue encodedOp1);
    103102EncodedJSValue DFG_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r115248 r116670  
    30303030        // otherwise we'd start taking slow path a lot).
    30313031       
    3032         SpeculateCellOperand proto(this, node.child1());
     3032        SpeculateCellOperand callee(this, node.child1());
    30333033        GPRTemporary result(this);
    30343034        GPRTemporary scratch(this);
    30353035       
    3036         GPRReg protoGPR = proto.gpr();
     3036        GPRReg calleeGPR = callee.gpr();
    30373037        GPRReg resultGPR = result.gpr();
    30383038        GPRReg scratchGPR = scratch.gpr();
    30393039       
    3040         proto.use();
    3041        
     3040        // Load the inheritorID. If the inheritorID is not set, go to slow path.
     3041        m_jit.loadPtr(MacroAssembler::Address(calleeGPR, JSFunction::offsetOfCachedInheritorID()), scratchGPR);
    30423042        MacroAssembler::JumpList slowPath;
    3043        
    3044         // Need to verify that the prototype is an object. If we have reason to believe
    3045         // that it's a FinalObject then we speculate on that directly. Otherwise we
    3046         // do the slow (structure-based) check.
    3047         if (at(node.child1()).shouldSpeculateFinalObject()) {
    3048             if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
    3049                 speculationCheck(BadType, JSValueSource::unboxedCell(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info)));
    3050         } else {
    3051             m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
    3052             slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
    3053         }
    3054        
    3055         // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
    3056         // use to refer to that prototype). If the inheritorID is not set, go to slow path.
    3057         m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
    30583043        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
    30593044       
     
    30653050       
    30663051        silentSpillAllRegisters(resultGPR);
    3067         if (node.codeOrigin.inlineCallFrame)
    3068             callOperation(operationCreateThisInlined, resultGPR, protoGPR, node.codeOrigin.inlineCallFrame->callee.get());
    3069         else
    3070             callOperation(operationCreateThis, resultGPR, protoGPR);
     3052        callOperation(operationCreateThis, resultGPR, calleeGPR);
    30713053        silentFillAllRegisters(resultGPR);
    30723054       
    30733055        done.link(&m_jit);
    30743056       
    3075         cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
     3057        cellResult(resultGPR, m_compileIndex);
    30763058        break;
    30773059    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r115248 r116670  
    30543054        // otherwise we'd start taking slow path a lot).
    30553055       
    3056         SpeculateCellOperand proto(this, node.child1());
     3056        SpeculateCellOperand callee(this, node.child1());
    30573057        GPRTemporary result(this);
    30583058        GPRTemporary scratch(this);
    30593059       
    3060         GPRReg protoGPR = proto.gpr();
     3060        GPRReg calleeGPR = callee.gpr();
    30613061        GPRReg resultGPR = result.gpr();
    30623062        GPRReg scratchGPR = scratch.gpr();
    30633063       
    3064         proto.use();
    3065        
     3064        // Load the inheritorID. If the inheritorID is not set, go to slow path.
     3065        m_jit.loadPtr(MacroAssembler::Address(calleeGPR, JSFunction::offsetOfCachedInheritorID()), scratchGPR);
    30663066        MacroAssembler::JumpList slowPath;
    3067        
    3068         // Need to verify that the prototype is an object. If we have reason to believe
    3069         // that it's a FinalObject then we speculate on that directly. Otherwise we
    3070         // do the slow (structure-based) check.
    3071         if (at(node.child1()).shouldSpeculateFinalObject()) {
    3072             if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
    3073                 speculationCheck(BadType, JSValueRegs(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info)));
    3074         } else {
    3075             m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
    3076             slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
    3077         }
    3078        
    3079         // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
    3080         // use to refer to that prototype). If the inheritorID is not set, go to slow path.
    3081         m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
    30823067        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
    30833068       
     
    30893074       
    30903075        silentSpillAllRegisters(resultGPR);
    3091         if (node.codeOrigin.inlineCallFrame)
    3092             callOperation(operationCreateThisInlined, resultGPR, protoGPR, node.codeOrigin.inlineCallFrame->callee.get());
    3093         else
    3094             callOperation(operationCreateThis, resultGPR, protoGPR);
     3076        callOperation(operationCreateThis, resultGPR, calleeGPR);
    30953077        silentFillAllRegisters(resultGPR);
    30963078       
    30973079        done.link(&m_jit);
    30983080       
    3099         cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
     3081        cellResult(resultGPR, m_compileIndex);
    31003082        break;
    31013083    }
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r116455 r116670  
    48104810
    48114811        int thisRegister = vPC[1].u.operand;
    4812         int protoRegister = vPC[2].u.operand;
    48134812
    48144813        JSFunction* constructor = jsCast<JSFunction*>(callFrame->callee());
     
    48184817#endif
    48194818
    4820         Structure* structure;
    4821         JSValue proto = callFrame->r(protoRegister).jsValue();
    4822         if (proto.isObject())
    4823             structure = asObject(proto)->inheritorID(callFrame->globalData());
    4824         else
    4825             structure = constructor->scope()->globalObject->emptyObjectStructure();
     4819        Structure* structure = constructor->cachedInheritorID(callFrame);
    48264820        callFrame->uncheckedR(thisRegister) = constructEmptyObject(callFrame, structure);
    48274821
  • trunk/Source/JavaScriptCore/jit/JITInlineMethods.h

    r115141 r116670  
    449449    storePtr(TrustedImmPtr(executable), Address(result, JSFunction::offsetOfExecutable()));
    450450
     451    // clear the function's inheritorID
     452    storePtr(TrustedImmPtr(0), Address(result, JSFunction::offsetOfCachedInheritorID()));
     453
    451454    // store the function's name
    452455    ASSERT(executable->nameValue());
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r115096 r116670  
    12731273void JIT::emit_op_create_this(Instruction* currentInstruction)
    12741274{
    1275     emitGetVirtualRegister(currentInstruction[2].u.operand, regT2);
    1276     emitJumpSlowCaseIfNotJSCell(regT2, currentInstruction[2].u.operand);
    1277     loadPtr(Address(regT2, JSCell::structureOffset()), regT1);
    1278     addSlowCase(emitJumpIfNotObject(regT1));
    1279    
    1280     // now we know that the prototype is an object, but we don't know if it's got an
    1281     // inheritor ID
    1282    
    1283     loadPtr(Address(regT2, JSObject::offsetOfInheritorID()), regT2);
     1275    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
     1276    loadPtr(Address(regT0, JSFunction::offsetOfCachedInheritorID()), regT2);
    12841277    addSlowCase(branchTestPtr(Zero, regT2));
    12851278   
     
    12881281   
    12891282    emitAllocateJSFinalObject(regT2, regT0, regT1);
    1290    
    12911283    emitPutVirtualRegister(currentInstruction[1].u.operand);
    12921284}
     
    12941286void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    12951287{
    1296     linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand); // not a cell
    1297     linkSlowCase(iter); // not an object
    12981288    linkSlowCase(iter); // doesn't have an inheritor ID
    12991289    linkSlowCase(iter); // allocation failed
    13001290    JITStubCall stubCall(this, cti_op_create_this);
    1301     stubCall.addArgument(currentInstruction[2].u.operand, regT1);
    13021291    stubCall.call(currentInstruction[1].u.operand);
    13031292}
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r114702 r116670  
    15331533void JIT::emit_op_create_this(Instruction* currentInstruction)
    15341534{
    1535     emitLoad(currentInstruction[2].u.operand, regT1, regT0);
    1536     emitJumpSlowCaseIfNotJSCell(currentInstruction[2].u.operand, regT1);
    1537     loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
    1538     addSlowCase(emitJumpIfNotObject(regT1));
    1539    
    1540     // now we know that the prototype is an object, but we don't know if it's got an
    1541     // inheritor ID
    1542    
    1543     loadPtr(Address(regT0, JSObject::offsetOfInheritorID()), regT2);
     1535    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
     1536    loadPtr(Address(regT0, JSFunction::offsetOfCachedInheritorID()), regT2);
    15441537    addSlowCase(branchTestPtr(Zero, regT2));
    15451538   
     
    15481541   
    15491542    emitAllocateJSFinalObject(regT2, regT0, regT1);
    1550 
    15511543    emitStoreCell(currentInstruction[1].u.operand, regT0);
    15521544}
     
    15541546void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    15551547{
    1556     linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand); // not a cell
    1557     linkSlowCase(iter); // not an object
    15581548    linkSlowCase(iter); // doesn't have an inheritor ID
    15591549    linkSlowCase(iter); // allocation failed
    1560     unsigned protoRegister = currentInstruction[2].u.operand;
    1561     emitLoad(protoRegister, regT1, regT0);
    15621550    JITStubCall stubCall(this, cti_op_create_this);
    1563     stubCall.addArgument(regT1, regT0);
    15641551    stubCall.call(currentInstruction[1].u.operand);
    15651552}
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r116494 r116670  
    12871287#endif
    12881288
    1289     Structure* structure;
    1290     JSValue proto = stackFrame.args[0].jsValue();
    1291     if (proto.isObject())
    1292         structure = asObject(proto)->inheritorID(*stackFrame.globalData);
    1293     else
    1294         structure = constructor->scope()->globalObject->emptyObjectStructure();
     1289    Structure* structure = constructor->cachedInheritorID(callFrame);
    12951290    JSValue result = constructEmptyObject(callFrame, structure);
    12961291
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r116363 r116670  
    459459#endif
    460460   
    461     Structure* structure;
    462     JSValue proto = LLINT_OP(2).jsValue();
    463     if (proto.isObject())
    464         structure = asObject(proto)->inheritorID(globalData);
    465     else
    466         structure = constructor->scope()->globalObject->emptyObjectStructure();
    467    
     461    Structure* structure = constructor->cachedInheritorID(exec);
    468462    LLINT_RETURN(constructEmptyObject(exec, structure));
    469463}
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r116361 r116670  
    344344_llint_op_create_this:
    345345    traceExecution()
    346     loadi 8[PC], t0
    347     assertNotConstant(t0)
    348     bineq TagOffset[cfr, t0, 8], CellTag, .opCreateThisSlow
    349     loadi PayloadOffset[cfr, t0, 8], t0
    350     loadp JSCell::m_structure[t0], t1
    351     bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
    352     loadp JSObject::m_inheritorID[t0], t2
     346    loadp Callee[cfr], t0
     347    loadp JSFunction::m_cachedInheritorID[t0], t2
    353348    btpz t2, .opCreateThisSlow
    354349    allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
     
    356351    storei CellTag, TagOffset[cfr, t1, 8]
    357352    storei t0, PayloadOffset[cfr, t1, 8]
    358     dispatch(3)
     353    dispatch(2)
    359354
    360355.opCreateThisSlow:
    361356    callSlowPath(_llint_slow_path_create_this)
    362     dispatch(3)
     357    dispatch(2)
    363358
    364359
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r116361 r116670  
    222222_llint_op_create_this:
    223223    traceExecution()
    224     loadis 16[PB, PC, 8], t0
    225     assertNotConstant(t0)
    226     loadp [cfr, t0, 8], t0
    227     btpnz t0, tagMask, .opCreateThisSlow
    228     loadp JSCell::m_structure[t0], t1
    229     bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
    230     loadp JSObject::m_inheritorID[t0], t2
     224    loadp Callee[cfr], t0
     225    loadp JSFunction::m_cachedInheritorID[t0], t2
    231226    btpz t2, .opCreateThisSlow
    232227    allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
    233228    loadis 8[PB, PC, 8], t1
    234229    storep t0, [cfr, t1, 8]
    235     dispatch(3)
     230    dispatch(2)
    236231
    237232.opCreateThisSlow:
    238233    callSlowPath(_llint_slow_path_create_this)
    239     dispatch(3)
     234    dispatch(2)
    240235
    241236
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r112285 r116670  
    113113}
    114114
     115Structure* JSFunction::cacheInheritorID(ExecState* exec)
     116{
     117    JSValue prototype = get(exec, exec->globalData().propertyNames->prototype);
     118    if (prototype.isObject())
     119        m_cachedInheritorID.set(exec->globalData(), this, asObject(prototype)->inheritorID(exec->globalData()));
     120    else
     121        m_cachedInheritorID.set(exec->globalData(), this, globalObject()->emptyObjectStructure());
     122    return m_cachedInheritorID.get();
     123}
     124
    115125const UString& JSFunction::name(ExecState* exec)
    116126{
     
    333343        PropertySlot slot;
    334344        thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
     345        thisObject->m_cachedInheritorID.clear();
    335346    }
    336347    if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
     
    373384        PropertySlot slot;
    374385        thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
     386        thisObject->m_cachedInheritorID.clear();
    375387        return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
    376388    }
  • trunk/Source/JavaScriptCore/runtime/JSFunction.h

    r111739 r116670  
    122122        }
    123123
     124        Structure* cachedInheritorID(ExecState* exec)
     125        {
     126            if (UNLIKELY(!m_cachedInheritorID))
     127                return cacheInheritorID(exec);
     128            return m_cachedInheritorID.get();
     129        }
     130
     131        static size_t offsetOfCachedInheritorID()
     132        {
     133            return OBJECT_OFFSETOF(JSFunction, m_cachedInheritorID);
     134        }
     135
    124136    protected:
    125137        const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
     
    130142        void finishCreation(ExecState*, NativeExecutable*, int length, const Identifier& name);
    131143        void finishCreation(ExecState*, FunctionExecutable*, ScopeChainNode*);
     144
     145        Structure* cacheInheritorID(ExecState*);
    132146
    133147        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
     
    153167        WriteBarrier<ExecutableBase> m_executable;
    154168        WriteBarrier<ScopeChainNode> m_scopeChain;
     169        WriteBarrier<Structure> m_cachedInheritorID;
    155170    };
    156171
Note: See TracChangeset for help on using the changeset viewer.