Ignore:
Timestamp:
Aug 25, 2020, 12:45:00 AM (5 years ago)
Author:
Alexey Shvayka
Message:

Implementation of the class "extends" clause incorrectly uses proto for setting prototypes
https://bugs.webkit.org/show_bug.cgi?id=205848

Reviewed by Keith Miller.

JSTests:

  • microbenchmarks/class-derived-creation.js: Added.
  • test262/expectations.yaml: Mark 4 test cases as passing.

Source/JavaScriptCore:

To prevent class extends from breaking if Object.prototype.proto is overridden
or removed, this patch replaces OpPutById bytecodes in ClassExprNode::emitBytecode()
with JSObject::setPrototypeDirect() invocations via OpCall.

Since the spec sets Prototype values directly [1], we are safe to skip method
table lookups and cycle checks.

Although this approach adds 4 mov ops to emitted bytecode for class extends creation,
increasing instruction count to 35, I prefer it over introducing a slow path only op.
To avoid emitting 2 extra mov ops, globalFuncSetPrototypeDirect() uses thisRegister().

Aligns JSC with V8 and SpiderMonkey. Derived class creation microbenchmark is neutral.

[1]: https://tc39.es/ecma262/#sec-createbuiltinfunction (step 7)

  • builtins/BuiltinNames.h:
  • bytecode/BytecodeDumper.cpp:

(JSC::CodeBlockBytecodeDumper<Block>::dumpConstants): Fix typo.

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

(JSC::BytecodeGenerator::emitSetPrototypeOf):

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

(JSC::ClassExprNode::emitBytecode):

  • parser/Nodes.h:
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):

File:
1 edited

Legend:

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

    r265934 r266106  
    731731}
    732732
     733EncodedJSValue JSC_HOST_CALL globalFuncSetPrototypeDirect(JSGlobalObject* globalObject, CallFrame* callFrame)
     734{
     735    VM& vm = globalObject->vm();
     736
     737    JSValue value = callFrame->uncheckedArgument(0);
     738    ASSERT(value.isObject() || value.isNull());
     739
     740    JSObject* object = asObject(callFrame->thisValue());
     741    object->setPrototypeDirect(vm, value);
     742
     743    return { };
     744}
     745
    733746EncodedJSValue JSC_HOST_CALL globalFuncHostPromiseRejectionTracker(JSGlobalObject* globalObject, CallFrame* callFrame)
    734747{
Note: See TracChangeset for help on using the changeset viewer.