Ignore:
Timestamp:
Jun 15, 2020, 7:42:43 AM (5 years ago)
Author:
Alexey Shvayka
Message:

super should not depend on proto
https://bugs.webkit.org/show_bug.cgi?id=157972

Reviewed by Saam Barati.

JSTests:

  • microbenchmarks/object-get-prototype-of-primitive.js: Added.
  • stress/class-syntax-derived-default-constructor.js:
  • stress/get-prototype-of.js: Added.
  • stress/super-property-access.js:
  • test262/expectations.yaml: Mark 4 test cases as passing.

Source/JavaScriptCore:

Before this change, both super() call [1] and super.property [2] relied on
Object.prototype.proto to acquire super base, which was observable and
incorrect if proto gets removed.

This patch introduces get_prototype_of bytecode, ensuring returned values
are profiled so the op can be wired to existing DFG and FTL implementations.
In order to avoid performance regression w/o DFG (proto is optimized via
IntrinsicGetterAccessCase), fast paths for LLInt and baseline JIT are added
(64-bit only), utilizing OverridesGetPrototypeOutOfLine type info flag.

This change aligns JSC with V8 and SpiderMonkey, progressing microbenchmarks/
super-get-by-{id,val}-with-this-monomorphic.js by 7-10%. SixSpeed is neutral.

Also, extracts JSValue::getPrototype() method to avoid code duplication and
utilizes it in objectConstructorGetPrototypeOf(), advancing provided
microbenchmark by 40%.

[1]: https://tc39.es/ecma262/#sec-getsuperconstructor (step 5)
[2]: https://tc39.es/ecma262/#sec-getsuperbase (step 5)

  • builtins/BuiltinNames.h:
  • bytecode/BytecodeIntrinsicRegistry.h:
  • bytecode/BytecodeList.rb:
  • bytecode/BytecodeUseDef.cpp:

(JSC::computeUsesForBytecodeIndexImpl):
(JSC::computeDefsForBytecodeIndexImpl):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):

  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitGetPrototypeOf):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::emitSuperBaseForCallee):
(JSC::emitGetSuperFunctionForConstruct):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_getPrototypeOf):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGOperations.cpp:
  • jit/IntrinsicEmitter.cpp:

(JSC::IntrinsicGetterAccessCase::canEmitIntrinsicGetter):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_get_prototype_of):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/CommonSlowPaths.h:
  • runtime/JSCJSValue.h:
  • runtime/JSCJSValueInlines.h:

(JSC::JSValue::getPrototype const):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::globalFuncProtoGetter):

  • runtime/JSObject.cpp:

(JSC::JSObject::calculatedClassName):

  • runtime/JSObject.h:

(JSC::JSObject::getPrototype):

  • runtime/JSObjectInlines.h:

(JSC::JSObject::canPerformFastPutInlineExcludingProto):
(JSC::JSObject::getPropertySlot):
(JSC::JSObject::getNonIndexPropertySlot):

  • runtime/JSProxy.h:
  • runtime/JSTypeInfo.h:

(JSC::TypeInfo::overridesGetPrototype const):

  • runtime/ObjectConstructor.cpp:

(JSC::objectConstructorGetPrototypeOf):

  • runtime/ProxyObject.h:
  • runtime/Structure.h:
  • runtime/Structure.cpp:

(JSC::Structure::validateFlags):

Source/WebCore:

No new tests, no behavior change.

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateHeader): Set OverridesGetPrototype structure flag for CustomGetPrototype IDL attribute.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r262995 r263035  
    197197{
    198198    RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
    199     return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
     199    return generator.emitGetPrototypeOf(generator.newTemporary(), homeObject.get());
    200200}
    201201
     
    203203{
    204204    if (generator.isDerivedConstructorContext())
    205         return generator.emitGetById(generator.newTemporary(), generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment(), generator.propertyNames().underscoreProto);
     205        return generator.emitGetPrototypeOf(generator.newTemporary(), generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment());
    206206
    207207    RegisterID callee;
    208208    callee.setIndex(CallFrameSlot::callee);
    209     return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().underscoreProto);
     209    return generator.emitGetPrototypeOf(generator.newTemporary(), &callee);
    210210}
    211211
     
    11551155    ASSERT(!node->m_next);
    11561156    return generator.emitDirectGetById(generator.finalDestination(dst), base.get(), generator.parserArena().identifierArena().makeIdentifier(generator.vm(), symbol));
     1157}
     1158
     1159RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getPrototypeOf(BytecodeGenerator& generator, RegisterID* dst)
     1160{
     1161    ArgumentListNode* node = m_args->m_listNode;
     1162    RefPtr<RegisterID> value = generator.emitNode(node);
     1163    ASSERT(!node->m_next);
     1164    return generator.emitGetPrototypeOf(generator.finalDestination(dst), value.get());
    11571165}
    11581166
Note: See TracChangeset for help on using the changeset viewer.