Changeset 181611 in webkit


Ignore:
Timestamp:
Mar 16, 2015 9:02:52 PM (9 years ago)
Author:
rniwa@webkit.org
Message:

Source/JavaScriptCore:
Add support for default constructor
https://bugs.webkit.org/show_bug.cgi?id=142388

Reviewed by Filip Pizlo.

Added the support for default constructors. They're generated by ClassExprNode::emitBytecode
via BuiltinExecutables::createDefaultConstructor.

UnlinkedFunctionExecutable now has the ability to override SourceCode provided by the owner
executable. We can't make store SourceCode in UnlinkedFunctionExecutable since CodeCache can use
the same UnlinkedFunctionExecutable to generate code blocks for multiple functions.

Parser now has the ability to treat any function expression as a constructor of the kind specified
by m_defaultConstructorKind member variable.

  • builtins/BuiltinExecutables.cpp:

(JSC::BuiltinExecutables::createDefaultConstructor): Added.
(JSC::BuiltinExecutables::createExecutableInternal): Generalized from createBuiltinExecutable.
Parse default constructors as normal non-builtin functions. Override SourceCode in the unlinked
function executable since the Miranda function's code is definitely not in the owner executable's
source code. That's the whole point.

  • builtins/BuiltinExecutables.h:

(UnlinkedFunctionExecutable::createBuiltinExecutable): Added. Wraps createExecutableInternal.

  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::UnlinkedFunctionExecutable::linkInsideExecutable):
(JSC::UnlinkedFunctionExecutable::linkGlobalCode):

  • bytecode/UnlinkedCodeBlock.h:

(JSC::UnlinkedFunctionExecutable::create):
(JSC::UnlinkedFunctionExecutable::symbolTable): Deleted.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitNewDefaultConstructor): Added.

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

(JSC::ClassExprNode::emitBytecode): Generate the default constructor if needed.

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::parseFunctionInfo): Override ownerClassKind and assume the function as
a constructor if we're parsing a default constructor.
(JSC::Parser<LexerType>::parseClass): Allow omission of the class constructor.

  • parser/Parser.h:

(JSC::parse):

LayoutTests:
Implement default constructor

Add support for default constructor
https://bugs.webkit.org/show_bug.cgi?id=142388

Reviewed by Filip Pizlo.

Added tests for default constructors.

  • TestExpectations: Skipped the test since ES6 class syntax isn't enabled by default.
  • js/class-syntax-default-constructor-expected.txt: Added.
  • js/class-syntax-default-constructor.html: Added.
  • js/script-tests/class-syntax-default-constructor.js: Added.
Location:
trunk
Files:
3 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r181609 r181611  
     12015-03-16  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Implement default constructor
     4
     5        Add support for default constructor
     6        https://bugs.webkit.org/show_bug.cgi?id=142388
     7
     8        Reviewed by Filip Pizlo.
     9
     10        Added tests for default constructors.
     11
     12        * TestExpectations: Skipped the test since ES6 class syntax isn't enabled by default.
     13        * js/class-syntax-default-constructor-expected.txt: Added.
     14        * js/class-syntax-default-constructor.html: Added.
     15        * js/script-tests/class-syntax-default-constructor.js: Added.
     16
    1172015-03-16  Hunseop Jeong  <hs85.jeong@samsung.com>
    218
  • trunk/LayoutTests/TestExpectations

    r181592 r181611  
    7070webkit.org/b/140491 js/class-syntax-call.html [ Failure ]
    7171webkit.org/b/140491 js/class-syntax-declaration.html [ Failure ]
     72webkit.org/b/140491 js/class-syntax-default-constructor.html [ Failure ]
    7273webkit.org/b/140491 js/class-syntax-expression.html [ Failure ]
    7374webkit.org/b/140491 js/class-syntax-extends.html [ Failure ]
  • trunk/Source/JavaScriptCore/ChangeLog

    r181601 r181611  
     12015-03-16  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Add support for default constructor
     4        https://bugs.webkit.org/show_bug.cgi?id=142388
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Added the support for default constructors. They're generated by ClassExprNode::emitBytecode
     9        via BuiltinExecutables::createDefaultConstructor.
     10
     11        UnlinkedFunctionExecutable now has the ability to override SourceCode provided by the owner
     12        executable. We can't make store SourceCode in UnlinkedFunctionExecutable since CodeCache can use
     13        the same UnlinkedFunctionExecutable to generate code blocks for multiple functions.
     14
     15        Parser now has the ability to treat any function expression as a constructor of the kind specified
     16        by m_defaultConstructorKind member variable.
     17
     18        * builtins/BuiltinExecutables.cpp:
     19        (JSC::BuiltinExecutables::createDefaultConstructor): Added.
     20        (JSC::BuiltinExecutables::createExecutableInternal): Generalized from createBuiltinExecutable.
     21        Parse default constructors as normal non-builtin functions. Override SourceCode in the unlinked
     22        function executable since the Miranda function's code is definitely not in the owner executable's
     23        source code. That's the whole point.
     24        * builtins/BuiltinExecutables.h:
     25        (UnlinkedFunctionExecutable::createBuiltinExecutable): Added. Wraps createExecutableInternal.
     26        * bytecode/UnlinkedCodeBlock.cpp:
     27        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
     28        (JSC::UnlinkedFunctionExecutable::linkInsideExecutable):
     29        (JSC::UnlinkedFunctionExecutable::linkGlobalCode):
     30        * bytecode/UnlinkedCodeBlock.h:
     31        (JSC::UnlinkedFunctionExecutable::create):
     32        (JSC::UnlinkedFunctionExecutable::symbolTable): Deleted.
     33        * bytecompiler/BytecodeGenerator.cpp:
     34        (JSC::BytecodeGenerator::emitNewDefaultConstructor): Added.
     35        * bytecompiler/BytecodeGenerator.h:
     36        * bytecompiler/NodesCodegen.cpp:
     37        (JSC::ClassExprNode::emitBytecode): Generate the default constructor if needed.
     38        * parser/Parser.cpp:
     39        (JSC::Parser<LexerType>::Parser):
     40        (JSC::Parser<LexerType>::parseFunctionInfo): Override ownerClassKind and assume the function as
     41        a constructor if we're parsing a default constructor.
     42        (JSC::Parser<LexerType>::parseClass): Allow omission of the class constructor.
     43        * parser/Parser.h:
     44        (JSC::parse):
     45
    1462015-03-16  Alex Christensen  <achristensen@webkit.org>
    247
  • trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp

    r181248 r181611  
    3232#include "JSCInlines.h"
    3333#include "Parser.h"
     34#include <wtf/NeverDestroyed.h>
    3435
    3536namespace JSC {
     
    4344}
    4445
    45 UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const SourceCode& source, const Identifier& name)
     46UnlinkedFunctionExecutable* BuiltinExecutables::createDefaultConstructor(ConstructorKind constructorKind, const Identifier& name)
     47{
     48    static NeverDestroyed<const String> baseConstructorCode(ASCIILiteral("(function () { })"));
     49    static NeverDestroyed<const String> derivedConstructorCode(ASCIILiteral("(function () { super(...arguments); })"));
     50
     51    switch (constructorKind) {
     52    case ConstructorKind::None:
     53        break;
     54    case ConstructorKind::Base:
     55        return createExecutableInternal(makeSource(baseConstructorCode), name, constructorKind);
     56    case ConstructorKind::Derived:
     57        return createExecutableInternal(makeSource(derivedConstructorCode), name, constructorKind);
     58    }
     59    ASSERT_NOT_REACHED();
     60    return nullptr;
     61}
     62
     63UnlinkedFunctionExecutable* BuiltinExecutables::createExecutableInternal(const SourceCode& source, const Identifier& name, ConstructorKind constructorKind)
    4664{
    4765    JSTextPosition positionBeforeLastNewline;
    4866    ParserError error;
    49     std::unique_ptr<ProgramNode> program = parse<ProgramNode>(&m_vm, source, 0, Identifier(), JSParseBuiltin, JSParseProgramCode, error, &positionBeforeLastNewline);
     67    bool isParsingDefaultConstructor = constructorKind != ConstructorKind::None;
     68    JSParserStrictness strictness = isParsingDefaultConstructor ? JSParseNormal : JSParseBuiltin;
     69    UnlinkedFunctionKind kind = isParsingDefaultConstructor ? UnlinkedNormalFunction : UnlinkedBuiltinFunction;
     70    RefPtr<SourceProvider> sourceOverride = isParsingDefaultConstructor ? source.provider() : nullptr;
     71    std::unique_ptr<ProgramNode> program = parse<ProgramNode>(&m_vm, source, 0, Identifier(), strictness, JSParseProgramCode,
     72        error, &positionBeforeLastNewline, false, constructorKind);
    5073
    5174    if (!program) {
     
    79102    }
    80103    body->overrideName(name);
    81     UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&m_vm, source, body, UnlinkedBuiltinFunction);
     104    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&m_vm, source, body, kind, WTF::move(sourceOverride));
    82105    functionExecutable->m_nameValue.set(m_vm, functionExecutable, jsString(&m_vm, name.string()));
    83106    return functionExecutable;
  • trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.h

    r181248 r181611  
    2828
    2929#include "JSCBuiltins.h"
     30#include "ParserModes.h"
    3031#include "SourceCode.h"
    3132#include "Weak.h"
     
    4950    JSC_FOREACH_BUILTIN(EXPOSE_BUILTIN_EXECUTABLES)
    5051#undef EXPOSE_BUILTIN_SOURCES
    51    
     52
     53    UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name);
     54
    5255private:
    5356    void finalize(Handle<Unknown>, void* context) override;
    5457
    5558    VM& m_vm;
    56     UnlinkedFunctionExecutable* createBuiltinExecutable(const SourceCode&, const Identifier&);
     59
     60    UnlinkedFunctionExecutable* createBuiltinExecutable(const SourceCode& code, const Identifier& name)
     61    {
     62        return createExecutableInternal(code, name, ConstructorKind::None);
     63    }
     64    UnlinkedFunctionExecutable* createExecutableInternal(const SourceCode&, const Identifier&, ConstructorKind);
     65
    5766#define DECLARE_BUILTIN_SOURCE_MEMBERS(name, functionName, length)\
    5867    SourceCode m_##name##Source; \
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp

    r181490 r181611  
    8181}
    8282
    83 UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, FunctionBodyNode* node, UnlinkedFunctionKind kind)
     83UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, RefPtr<SourceProvider>&& sourceOverride, FunctionBodyNode* node, UnlinkedFunctionKind kind)
    8484    : Base(*vm, structure)
    8585    , m_isInStrictContext(node->isInStrictContext())
     
    9999    , m_typeProfilingStartOffset(node->functionKeywordStart())
    100100    , m_typeProfilingEndOffset(node->startStartOffset() + node->source().length() - 1)
     101    , m_sourceOverride(sourceOverride)
    101102    , m_features(0)
    102103    , m_functionMode(node->functionMode())
     
    122123}
    123124
    124 FunctionExecutable* UnlinkedFunctionExecutable::linkInsideExecutable(VM& vm, const SourceCode& source)
    125 {
     125FunctionExecutable* UnlinkedFunctionExecutable::linkInsideExecutable(VM& vm, const SourceCode& ownerSource)
     126{
     127    SourceCode source = m_sourceOverride ? SourceCode(m_sourceOverride) : ownerSource;
    126128    unsigned firstLine = source.firstLine() + m_firstLineOffset;
    127129    unsigned startOffset = source.startOffset() + m_startOffset;
     
    138140FunctionExecutable* UnlinkedFunctionExecutable::linkGlobalCode(VM& vm, const SourceCode& source)
    139141{
     142    ASSERT(!m_sourceOverride);
    140143    unsigned firstLine = source.firstLine() + m_firstLineOffset;
    141144    unsigned startOffset = source.startOffset() + m_startOffset;
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h

    r181490 r181611  
    104104    friend class VM;
    105105    typedef JSCell Base;
    106     static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node, UnlinkedFunctionKind unlinkedFunctionKind)
    107     {
    108         UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind);
     106    static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node, UnlinkedFunctionKind unlinkedFunctionKind, RefPtr<SourceProvider>&& sourceOverride = nullptr)
     107    {
     108        UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap))
     109            UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTF::move(sourceOverride), node, unlinkedFunctionKind);
    109110        instance->finishCreation(*vm);
    110111        return instance;
     
    174175
    175176private:
    176     UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionBodyNode*, UnlinkedFunctionKind);
     177    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr<SourceProvider>&& sourceOverride, FunctionBodyNode*, UnlinkedFunctionKind);
    177178    WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
    178179    WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
     
    198199    unsigned m_typeProfilingStartOffset;
    199200    unsigned m_typeProfilingEndOffset;
     201    RefPtr<SourceProvider> m_sourceOverride;
    200202
    201203    CodeFeatures m_features;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r181490 r181611  
    3232#include "BytecodeGenerator.h"
    3333
     34#include "BuiltinExecutables.h"
    3435#include "Interpreter.h"
    3536#include "JSFunction.h"
     
    16911692    instructions().append(index);
    16921693    return r0;
     1694}
     1695
     1696RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name)
     1697{
     1698    UnlinkedFunctionExecutable* executable = m_vm->builtinExecutables()->createDefaultConstructor(constructorKind, name);
     1699
     1700    unsigned index = m_codeBlock->addFunctionExpr(executable);
     1701
     1702    emitOpcode(op_new_func_exp);
     1703    instructions().append(dst->index());
     1704    instructions().append(scopeRegister()->index());
     1705    instructions().append(index);
     1706    return dst;
    16931707}
    16941708
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r181490 r181611  
    467467        RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index, bool shouldNullCheck);
    468468        RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
     469        RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name);
    469470        RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
    470471
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r181490 r181611  
    28862886    }
    28872887
    2888     RefPtr<RegisterID> constructor = generator.emitNode(dst, m_constructorExpression);
     2888    RefPtr<RegisterID> constructor;
     2889    RefPtr<RegisterID> prototype;
     2890
    28892891    // FIXME: Make the prototype non-configurable & non-writable.
    2890     RefPtr<RegisterID> prototype = generator.emitGetById(generator.newTemporary(), constructor.get(), generator.propertyNames().prototype);
     2892    if (m_constructorExpression)
     2893        constructor = generator.emitNode(dst, m_constructorExpression);
     2894    else {
     2895        constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst),
     2896            m_classHeritage ? ConstructorKind::Derived : ConstructorKind::Base, m_name);
     2897    }
     2898
     2899    prototype = generator.emitGetById(generator.newTemporary(), constructor.get(), generator.propertyNames().prototype);
    28912900
    28922901    if (superclass) {
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r181503 r181611  
    191191
    192192template <typename LexerType>
    193 Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode)
     193Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ConstructorKind defaultConstructorKind)
    194194    : m_vm(vm)
    195195    , m_source(&source)
     
    205205    , m_sourceElements(0)
    206206    , m_parsingBuiltin(strictness == JSParseBuiltin)
     207    , m_defaultConstructorKind(defaultConstructorKind)
    207208{
    208209    m_lexer = std::make_unique<LexerType>(vm, strictness);
     
    13261327    // Set ConstructorKind to None for non-constructor methods of classes.
    13271328    bool isClassConstructor = mode == MethodMode && info.name && *info.name == m_vm->propertyNames->constructor;
     1329    if (m_defaultConstructorKind != ConstructorKind::None) {
     1330        ownerClassKind = m_defaultConstructorKind;
     1331        isClassConstructor = true;
     1332    }
    13281333    ConstructorKind constructorKind = isClassConstructor ? ownerClassKind : ConstructorKind::None;
    13291334
     
    15491554        }
    15501555    }
    1551 
    1552     // FIXME: Create a Miranda function instead.
    1553     semanticFailIfFalse(constructor, "Class declaration without a constructor is not supported yet");
    15541556
    15551557    failIfFalse(popScope(classScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error");
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r181490 r181611  
    427427
    428428public:
    429     Parser(VM*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode);
     429    Parser(VM*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode,
     430        ConstructorKind defaultConstructorKind = ConstructorKind::None);
    430431    ~Parser();
    431432
     
    873874    SourceElements* m_sourceElements;
    874875    bool m_parsingBuiltin;
     876    ConstructorKind m_defaultConstructorKind;
    875877    DeclarationStacks::VarStack m_varDeclarations;
    876878    DeclarationStacks::FunctionStack m_funcDeclarations;
     
    980982
    981983template <class ParsedNode>
    982 std::unique_ptr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0, bool needReparsingAdjustment = false)
     984std::unique_ptr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name,
     985    JSParserStrictness strictness, JSParserMode parserMode, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0,
     986    bool needReparsingAdjustment = false, ConstructorKind defaultConstructorKind = ConstructorKind::None)
    983987{
    984988    SamplingRegion samplingRegion("Parsing");
     
    986990    ASSERT(!source.provider()->source().isNull());
    987991    if (source.provider()->source().is8Bit()) {
    988         Parser<Lexer<LChar>> parser(vm, source, parameters, name, strictness, parserMode);
     992        Parser<Lexer<LChar>> parser(vm, source, parameters, name, strictness, parserMode, defaultConstructorKind);
    989993        std::unique_ptr<ParsedNode> result = parser.parse<ParsedNode>(error, needReparsingAdjustment);
    990994        if (positionBeforeLastNewline)
Note: See TracChangeset for help on using the changeset viewer.