Ignore:
Timestamp:
May 22, 2009, 6:48:32 PM (16 years ago)
Author:
[email protected]
Message:

2009-05-21 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

op_method_check

Optimize method calls, by caching specific function values within the Structure.
The new opcode is used almost like an x86 opcode prefix byte to optimize op_get_by_id,
where the property access is being used to read a function to be passed to op-call (i.e.
'foo.bar();'). This patch modifies the Structure class such that when a property is
put to an object for the first time we will check if the value is a function. If it is,
we will cache the function value on the Structure. A Structure in such a state guarantees
that not only does a property with the given identifier exist on the object, but also that
its value is unchanged. Upon any further attempt to put a property with the same identifier
(but a different value) to the object, it will transition back to a normal Structure (where
it will guarantee the presence but not the value of the property).

op_method_check makes use of the new information made available by the Structure, by
augmenting the functionality of op_get_by_id. Upon generating a FunctionCallDotNode a
check will be emitted prior to the property access reading the function value, and the JIT
will generate an extra (initially unlinked but patchable) set of checks prior to the regular
JIT code for get_by_id. The new code will do inline structure and prototype structure check
(unlike a regular get_by_id, which can only handle 'self' accesses inline), and then performs
an immediate load of the function value, rather than using memory accesses to load the value
from the obejct's property storage array. If the method check fails it will revert, or if
the access is polymorphic, the op_get_by_id will continue to operate - and optimize itself -
just as any other regular op_get_by_id would.

~2.5% on v8-tests, due to a ~9% progression on richards.

  • API/JSCallbackObjectFunctions.h: (JSC::::put): (JSC::::staticFunctionGetter):
  • API/JSObjectRef.cpp: (JSObjectMakeConstructor):
  • JavaScriptCore.exp:
  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::differenceBetween):
  • assembler/MacroAssemblerX86.h: (JSC::MacroAssemblerX86::moveWithPatch):
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump):
  • bytecode/CodeBlock.h: (JSC::getMethodCallLinkInfoReturnLocation): (JSC::CodeBlock::getMethodCallLinkInfo): (JSC::CodeBlock::addMethodCallLinkInfos): (JSC::CodeBlock::methodCallLinkInfo):
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitMethodCheck):
  • bytecompiler/BytecodeGenerator.h:
  • interpreter/Interpreter.cpp: (JSC::Interpreter::privateExecute):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases): (JSC::JIT::privateCompile):
  • jit/JIT.h: (JSC::MethodCallCompilationInfo::MethodCallCompilationInfo):
  • jit/JITOpcodes.cpp:
  • jit/JITPropertyAccess.cpp: (JSC::JIT::emit_op_method_check): (JSC::JIT::emitSlow_op_method_check): (JSC::JIT::emit_op_get_by_id): (JSC::JIT::emitSlow_op_get_by_id): (JSC::JIT::emit_op_put_by_id): (JSC::JIT::emitSlow_op_put_by_id): (JSC::JIT::compileGetByIdHotPath): (JSC::JIT::compileGetByIdSlowCase): (JSC::JIT::patchMethodCallProto):
  • jit/JITStubs.cpp: (JSC::JITStubs::cti_op_get_by_id_method_check): (JSC::JITStubs::cti_op_get_by_id_method_check_second):
  • jit/JITStubs.h:
  • jsc.cpp: (GlobalObject::GlobalObject):
  • parser/Nodes.cpp: (JSC::FunctionCallDotNode::emitBytecode):
  • runtime/Arguments.cpp: (JSC::Arguments::put):
  • runtime/ArrayConstructor.cpp: (JSC::ArrayConstructor::ArrayConstructor):
  • runtime/BooleanConstructor.cpp: (JSC::BooleanConstructor::BooleanConstructor):
  • runtime/DateConstructor.cpp: (JSC::DateConstructor::DateConstructor):
  • runtime/ErrorConstructor.cpp: (JSC::ErrorConstructor::ErrorConstructor): (JSC::constructError):
  • runtime/ErrorPrototype.cpp: (JSC::ErrorPrototype::ErrorPrototype):
  • runtime/FunctionConstructor.cpp: (JSC::FunctionConstructor::FunctionConstructor):
  • runtime/FunctionPrototype.cpp: (JSC::FunctionPrototype::FunctionPrototype):
  • runtime/InternalFunction.cpp: (JSC::InternalFunction::InternalFunction):
  • runtime/JSActivation.cpp: (JSC::JSActivation::put): (JSC::JSActivation::putWithAttributes):
  • runtime/JSByteArray.cpp: (JSC::JSByteArray::JSByteArray):
  • runtime/JSFunction.cpp: (JSC::JSFunction::JSFunction): (JSC::JSFunction::getOwnPropertySlot):
  • runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::putWithAttributes): (JSC::JSGlobalObject::reset): (JSC::JSGlobalObject::mark):
  • runtime/JSGlobalObject.h: (JSC::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData): (JSC::JSGlobalObject::methodCallDummy):
  • runtime/JSObject.cpp: (JSC::JSObject::put): (JSC::JSObject::putWithAttributes): (JSC::JSObject::deleteProperty): (JSC::JSObject::defineGetter): (JSC::JSObject::defineSetter): (JSC::JSObject::getPropertyAttributes): (JSC::JSObject::getPropertySpecificFunction): (JSC::JSObject::putDirectFunction): (JSC::JSObject::putDirectFunctionWithoutTransition):
  • runtime/JSObject.h: (JSC::getJSFunction): (JSC::JSObject::getDirectLocation): (JSC::JSObject::putDirect): (JSC::JSObject::putDirectWithoutTransition):
  • runtime/LiteralParser.cpp: (JSC::LiteralParser::parseObject):
  • runtime/Lookup.cpp: (JSC::setUpStaticFunctionSlot):
  • runtime/Lookup.h: (JSC::lookupPut):
  • runtime/MathObject.cpp: (JSC::MathObject::MathObject):
  • runtime/NativeErrorConstructor.cpp: (JSC::NativeErrorConstructor::NativeErrorConstructor): (JSC::NativeErrorConstructor::construct):
  • runtime/NativeErrorPrototype.cpp: (JSC::NativeErrorPrototype::NativeErrorPrototype):
  • runtime/NumberConstructor.cpp: (JSC::NumberConstructor::NumberConstructor):
  • runtime/ObjectConstructor.cpp: (JSC::ObjectConstructor::ObjectConstructor):
  • runtime/PropertyMapHashTable.h: (JSC::PropertyMapEntry::PropertyMapEntry):
  • runtime/PrototypeFunction.cpp: (JSC::PrototypeFunction::PrototypeFunction):
  • runtime/PutPropertySlot.h: (JSC::PutPropertySlot::): (JSC::PutPropertySlot::PutPropertySlot): (JSC::PutPropertySlot::setNewProperty): (JSC::PutPropertySlot::setDespecifyFunctionProperty): (JSC::PutPropertySlot::isCacheable): (JSC::PutPropertySlot::cachedOffset):
  • runtime/RegExpConstructor.cpp: (JSC::RegExpConstructor::RegExpConstructor):
  • runtime/StringConstructor.cpp: (JSC::StringConstructor::StringConstructor):
  • runtime/StringPrototype.cpp: (JSC::StringPrototype::StringPrototype):
  • runtime/Structure.cpp: (JSC::Structure::Structure): (JSC::Structure::~Structure): (JSC::Structure::materializePropertyMap): (JSC::Structure::addPropertyTransitionToExistingStructure): (JSC::Structure::addPropertyTransition): (JSC::Structure::changeFunctionTransition): (JSC::Structure::addPropertyWithoutTransition): (JSC::Structure::get): (JSC::Structure::despecifyFunction): (JSC::Structure::put): (JSC::Structure::remove):
  • runtime/Structure.h: (JSC::Structure::get): (JSC::Structure::specificFunction):
  • runtime/StructureTransitionTable.h: (JSC::StructureTransitionTableHashTraits::emptyValue):
  • wtf/Platform.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/JSGlobalObject.cpp

    r43226 r44076  
    171171        JSValue valueAfter = getDirect(propertyName);
    172172        if (valueAfter)
    173             putDirect(propertyName, valueAfter, attributes);
     173            JSObject::putWithAttributes(exec, propertyName, valueAfter, attributes);
    174174    }
    175175}
     
    240240    d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype);
    241241
     242    d()->methodCallDummy = constructEmptyObject(exec);
     243
    242244    ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, ErrorPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
    243245    d()->errorStructure = ErrorInstance::createStructure(errorPrototype);
     
    254256    // Constructors
    255257
    256     JSValue objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype);
    257     JSValue functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype);
    258     JSValue arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype);
    259     JSValue stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
    260     JSValue booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype);
    261     JSValue numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype);
    262     JSValue dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype);
     258    JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype);
     259    JSCell* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype);
     260    JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype);
     261    JSCell* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
     262    JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype);
     263    JSCell* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype);
     264    JSCell* dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype);
    263265
    264266    d()->regExpConstructor = new (exec) RegExpConstructor(exec, RegExpConstructor::createStructure(d()->functionPrototype), d()->regExpPrototype);
     
    275277    d()->URIErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, URIErrorPrototype);
    276278
    277     d()->objectPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum);
    278     d()->functionPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum);
    279     d()->arrayPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum);
    280     d()->booleanPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum);
    281     d()->stringPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum);
    282     d()->numberPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum);
    283     d()->datePrototype->putDirectWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum);
    284     d()->regExpPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum);
    285     errorPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum);
     279    d()->objectPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum);
     280    d()->functionPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum);
     281    d()->arrayPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum);
     282    d()->booleanPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum);
     283    d()->stringPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum);
     284    d()->numberPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum);
     285    d()->datePrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum);
     286    d()->regExpPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum);
     287    errorPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum);
    286288
    287289    evalErrorPrototype->putDirect(exec->propertyNames().constructor, d()->evalErrorConstructor, DontEnum);
     
    296298    // FIXME: These properties could be handled by a static hash table.
    297299
    298     putDirectWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum);
    299     putDirectWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum);
    300     putDirectWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum);
    301     putDirectWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
    302     putDirectWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum);
    303     putDirectWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum);
    304     putDirectWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum);
    305     putDirectWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum);
    306     putDirectWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum);
    307     putDirectWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor);
    308     putDirectWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor);
    309     putDirectWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor);
    310     putDirectWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor);
    311     putDirectWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor);
    312     putDirectWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor);
     300    putDirectFunctionWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum);
     301    putDirectFunctionWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum);
     302    putDirectFunctionWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum);
     303    putDirectFunctionWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
     304    putDirectFunctionWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum);
     305    putDirectFunctionWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum);
     306    putDirectFunctionWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum);
     307    putDirectFunctionWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum);
     308    putDirectFunctionWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum);
     309    putDirectFunctionWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor);
     310    putDirectFunctionWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor);
     311    putDirectFunctionWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor);
     312    putDirectFunctionWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor);
     313    putDirectFunctionWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor);
     314    putDirectFunctionWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor);
    313315
    314316    // Set global values.
     
    388390    markIfNeeded(d()->regExpPrototype);
    389391
     392    markIfNeeded(d()->methodCallDummy);
     393
    390394    markIfNeeded(d()->errorStructure);
    391395
Note: See TracChangeset for help on using the changeset viewer.