Ignore:
Timestamp:
Dec 6, 2015, 12:56:30 PM (10 years ago)
Author:
[email protected]
Message:

[ES6] "super" and "this" should be lexically bound inside an arrow function and should live in a JSLexicalEnvironment
https://bugs.webkit.org/show_bug.cgi?id=149338

Source/JavaScriptCore:

Patch by Aleksandr Skachkov <[email protected]> on 2015-12-05
Reviewed by Saam Barati.

Implemented new version of the lexically bound 'this' in arrow function. In current version
'this' is stored inside of the lexical environment of the function. To store and load we use
op_get_from_scope and op_put_to_scope operations. Also new implementation prevent raising TDZ
error for arrow functions that are declared before super() but invoke after.

  • builtins/BuiltinExecutables.cpp:

(JSC::createExecutableInternal):

  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):

  • bytecode/EvalCodeCache.h:

(JSC::EvalCodeCache::getSlow):

  • bytecode/ExecutableInfo.h:

(JSC::ExecutableInfo::ExecutableInfo):
(JSC::ExecutableInfo::isDerivedConstructorContext):
(JSC::ExecutableInfo::isArrowFunctionContext):

  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):

  • bytecode/UnlinkedCodeBlock.h:

(JSC::UnlinkedCodeBlock::isArrowFunction):
(JSC::UnlinkedCodeBlock::isDerivedConstructorContext):
(JSC::UnlinkedCodeBlock::isArrowFunctionContext):

  • bytecode/UnlinkedFunctionExecutable.cpp:

(JSC::generateUnlinkedFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):

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

(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
(JSC::BytecodeGenerator::variable):
(JSC::BytecodeGenerator::emitNewArrowFunctionExpression):
(JSC::BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::emitLoadThisFromArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::emitPutNewTargetToArrowFunctionContextScope):
(JSC::BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope):
(JSC::BytecodeGenerator::emitPutThisToArrowFunctionContextScope):

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::isDerivedConstructorContext):
(JSC::BytecodeGenerator::usesArrowFunction):
(JSC::BytecodeGenerator::needsToUpdateArrowFunctionContext):
(JSC::BytecodeGenerator::usesEval):
(JSC::BytecodeGenerator::usesThis):
(JSC::BytecodeGenerator::newTarget):
(JSC::BytecodeGenerator::makeFunction):

  • bytecompiler/NodesCodegen.cpp:

(JSC::ThisNode::emitBytecode):
(JSC::SuperNode::emitBytecode):
(JSC::EvalFunctionCallNode::emitBytecode):
(JSC::FunctionCallValueNode::emitBytecode):
(JSC::FunctionNode::emitBytecode):

  • debugger/DebuggerCallFrame.cpp:

(JSC::DebuggerCallFrame::evaluate):

  • dfg/DFGAbstractInterpreterInlines.h:
  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGCapabilities.cpp:
  • dfg/DFGClobberize.h:
  • dfg/DFGDoesGC.cpp:
  • dfg/DFGFixupPhase.cpp:
  • dfg/DFGNodeType.h:
  • dfg/DFGObjectAllocationSinkingPhase.cpp:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGPromotedHeapLocation.cpp:
  • dfg/DFGPromotedHeapLocation.h:
  • dfg/DFGSafeToExecute.h:
  • dfg/DFGSpeculativeJIT.cpp:
  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGSpeculativeJIT32_64.cpp:
  • dfg/DFGSpeculativeJIT64.cpp:
  • ftl/FTLCapabilities.cpp:
  • ftl/FTLLowerDFGToLLVM.cpp:
  • ftl/FTLOperations.cpp:

(JSC::FTL::operationMaterializeObjectInOSR):

  • interpreter/Interpreter.cpp:

(JSC::eval):

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

(JSC::JIT::emitNewFuncExprCommon):

  • jit/JITOpcodes32_64.cpp:
  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createArrowFunctionExpr):
(JSC::ASTBuilder::usesArrowFunction):

  • parser/Nodes.h:

(JSC::ScopeNode::usesArrowFunction):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseFunctionInfo):

  • parser/ParserModes.h:
  • runtime/CodeCache.cpp:

(JSC::CodeCache::getGlobalCodeBlock):
(JSC::CodeCache::getProgramCodeBlock):
(JSC::CodeCache::getEvalCodeBlock):
(JSC::CodeCache::getModuleProgramCodeBlock):
(JSC::CodeCache::getFunctionExecutableFromGlobalCode):

  • runtime/CodeCache.h:
  • runtime/CommonIdentifiers.h:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/Executable.cpp:

(JSC::ScriptExecutable::ScriptExecutable):
(JSC::EvalExecutable::create):
(JSC::EvalExecutable::EvalExecutable):
(JSC::ProgramExecutable::ProgramExecutable):
(JSC::ModuleProgramExecutable::ModuleProgramExecutable):
(JSC::FunctionExecutable::FunctionExecutable):

  • runtime/Executable.h:

(JSC::ScriptExecutable::isArrowFunctionContext):
(JSC::ScriptExecutable::isDerivedConstructorContext):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::createEvalCodeBlock):

  • runtime/JSGlobalObject.h:
  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::globalFuncEval):

  • tests/es6.yaml:
  • tests/stress/arrowfunction-activation-sink-osrexit.js:
  • tests/stress/arrowfunction-activation-sink.js:
  • tests/stress/arrowfunction-lexical-bind-newtarget.js: Added.
  • tests/stress/arrowfunction-lexical-bind-supercall-1.js: Added.
  • tests/stress/arrowfunction-lexical-bind-supercall-2.js: Added.
  • tests/stress/arrowfunction-lexical-bind-supercall-3.js: Added.
  • tests/stress/arrowfunction-lexical-bind-supercall-4.js: Added.
  • tests/stress/arrowfunction-lexical-bind-this-1.js:
  • tests/stress/arrowfunction-lexical-bind-this-7.js: Added.
  • tests/stress/arrowfunction-tdz-1.js: Added.
  • tests/stress/arrowfunction-tdz-2.js: Added.
  • tests/stress/arrowfunction-tdz-3.js: Added.
  • tests/stress/arrowfunction-tdz-4.js: Added.
  • tests/stress/arrowfunction-tdz.js: Removed.

LayoutTests:

Patch by Skachkov Oleksandr <[email protected]> on 2015-12-06
Reviewed by Saam Barati.

  • js/arrowfunction-supercall-expected.txt: Added.
  • js/arrowfunction-supercall.html: Added.
  • js/arrowfunction-tdz-expected.txt: Added new expectation.
  • js/script-tests/arrowfunction-supercall.js: Added.
  • js/script-tests/arrowfunction-tdz.js: Added new cases.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/Executable.h

    r192937 r193584  
    345345    bool usesArguments() const { return m_features & ArgumentsFeature; }
    346346    bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature); }
     347    bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
    347348    bool isStrictMode() const { return m_features & StrictModeFeature; }
     349    bool isDerivedConstructorContext() const { return m_isDerivedConstructorContext; }
    348350    ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
    349351       
     
    394396
    395397protected:
    396     ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext);
     398    ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, bool isInDerivedConstructorContext, bool isInArrowFunctionContext);
    397399
    398400    void finishCreation(VM& vm)
     
    413415    bool m_neverOptimize { false };
    414416    bool m_didTryToEnterInLoop;
     417    bool m_isDerivedConstructorContext;
     418    bool m_isArrowFunctionContext;
    415419    int m_overrideLineNumber;
    416420    int m_firstLine;
     
    435439    }
    436440
    437     static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, const VariableEnvironment*);
     441    static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, bool isDerivedConstructorContext, bool isArrowFunctionContext, const VariableEnvironment*);
    438442
    439443    PassRefPtr<JITCode> generatedJITCode()
     
    449453    DECLARE_INFO;
    450454
    451     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ProgramMode); }
     455
     456    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, isDerivedConstructorContext(), isArrowFunctionContext()); }
    452457
    453458    unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
     
    457462    friend class ExecutableBase;
    458463    friend class ScriptExecutable;
    459     EvalExecutable(ExecState*, const SourceCode&, bool);
     464    EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, bool isDerivedConstructorContext, bool isArrowFunctionContext);
    460465
    461466    static void visitChildren(JSCell*, SlotVisitor&);
     
    502507    DECLARE_INFO;
    503508
    504     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ProgramMode); }
     509    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, isDerivedConstructorContext(), false); }
    505510
    506511private:
     
    543548    DECLARE_INFO;
    544549
    545     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode); }
     550    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, isDerivedConstructorContext(), false); }
     551
    546552    UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); }
    547553
     
    651657    bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
    652658    ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
     659    // TODO:Think about avoid using isArrowFunction veriabl
     660    bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
     661    bool isDerivedConstructorContext() const { return m_unlinkedExecutable->isDerivedConstructorContext(); }
    653662    bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
    654663    const Identifier& name() { return m_unlinkedExecutable->name(); }
     
    657666    size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
    658667    SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); }
    659     bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
    660668
    661669    static void visitChildren(JSCell*, SlotVisitor&);
Note: See TracChangeset for help on using the changeset viewer.