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/bytecompiler/NodesCodegen.cpp

    r265907 r266106  
    49094909        generator.emitLabel(protoParentIsObjectOrNullLabel.get());
    49104910
    4911         generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
     4911        generator.emitDirectSetPrototypeOf(tempRegister.get(), constructor.get(), superclass.get(), divot(), divotStart(), divotEnd());
    49124912        generator.emitLabel(superclassIsNullLabel.get());
    4913         generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
     4913        generator.emitDirectSetPrototypeOf(tempRegister.get(), prototype.get(), protoParent.get(), divot(), divotStart(), divotEnd());
    49144914    }
    49154915
Note: See TracChangeset for help on using the changeset viewer.