Changeset 215984 in webkit for trunk/Source/JavaScriptCore/jit


Ignore:
Timestamp:
Apr 30, 2017, 1:06:23 AM (8 years ago)
Author:
[email protected]
Message:

[ES6]. Implement Annex B.3.3 function hoisting rules for eval
https://bugs.webkit.org/show_bug.cgi?id=163208

Reviewed by Saam Barati.

JSTests:

  • stress/eval-func-decl-block-scoping-reassign.js: Added.

(assert):
(throw.new.Error.f):
(throw.new.Error):

  • stress/eval-func-decl-block-with-remove.js: Added.

(assert):
(foo.boo):
(foo):

  • stress/eval-func-decl-block-with-var-and-remove.js: Added.

(assert):
(assertThrow):
(foo):
(boo):
(joo):
(koo):

  • stress/eval-func-decl-block-with-var-sinthesize.js: Added.

(assert):
(assertThrow):
(foo):
(boo):
(hoo):
(joo):
(koo):

  • stress/eval-func-decl-in-block-scope-and-bind-to-top-eval-scope.js: Added.
  • stress/eval-func-decl-in-eval-within-block-with-let.js: Added.

(assert):
(assertThrow):
(foo):
(boo):
(goo):

  • stress/eval-func-decl-in-eval-within-with-scope.js: Added.

(assert):
(assertThrow):
(foo):
(boo):
(boo.let.val2):
(boo.let.val3):

  • stress/eval-func-decl-in-frozen-global.js: Added.

(assert):
(assertThrow):
(throw.new.Error):
(Object.freeze):

  • stress/eval-func-decl-in-global-of-eval.js: Added.

(assert):
(assertThrow):
(bar):
(baz):
(foobar):

  • stress/eval-func-decl-in-global.js: Added.

(assert):
(assertThrow):

  • stress/eval-func-decl-in-if.js: Added.

(assert):

  • stress/eval-func-decl-within-eval-with-reassign-to-var.js: Added.

(assert):
(assertThrow):
(foo):
(boo):
(foobar):
(hoo):
(joo):
(koo):
(loo):

  • stress/eval-func-decl-within-eval-without-reassign-to-let.js: Added.

(assert):
(assertThrow):
(foo):
(boo):
(goo):

  • stress/variable-under-tdz-eval-tricky.js:

(assert):

  • test262.yaml:

Source/JavaScriptCore:

Current patch implements Annex B.3.3 that is related to
hoisting of function declaration in eval.
https://tc39.github.io/ecma262/#sec-web-compat-evaldeclarationinstantiation
Function declaration in eval should create variable with
function name in function scope where eval is invoked
or bind to variable if it declared outside of the eval.
If variable is created it can be removed by 'delete a;' command.
If eval is invoke in block scope that contains let/const
variable with the same name as function declaration
we do not bind. This patch leads to the following behavior:

function foo() {

{

print(boo); undefined
eval('{ function boo() {}}');
print(boo);
function boo() {}

}
print(boo); function boo() {}

}

function foobar() {

{

let boo = 10;
print(boo); 10;
eval('{ function boo() {}}');
print(boo);
10;

}
print(boo) 10

}

function bar() {

{

var boo = 10;
print(boo); 10
eval('{ function boo() {} }');
print(boo);
function boo() {}

}
print(boo); function boo() {}

}

function bas() {

{

let boo = 10;
eval(' { function boo() {} } ');
print(boo); 10

}
print(boo); Reference Error

}

Current implementation relies on already implemented
'hoist function in sloppy mode' feature, with small changes.
In short it works in following way: during hoisting of function
with name S in eval, we are looking for first scope that
contains space for variable with name S and if this scope
has var type we bind function there

To implement this feature was added bytecode ops:
op_resolve_scope_for_hoisting_func_decl_in_eval - get variable scope
or return undefined if variable can't be binded there.

There is a corner case, hoist function in eval within catch block,
that is not covered by this patch, and will be fixed in
https://bugs.webkit.org/show_bug.cgi?id=168184

  • bytecode/BytecodeDumper.cpp:

(JSC::BytecodeDumper<Block>::dumpBytecode):

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

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finalizeLLIntInlineCaches):

  • bytecode/EvalCodeBlock.h:

(JSC::EvalCodeBlock::functionHoistingCandidate):
(JSC::EvalCodeBlock::numFunctionHoistingCandidates):

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

(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::hoistSloppyModeFunctionIfNecessary):
(JSC::BytecodeGenerator::emitResolveScopeForHoistingFuncDeclInEval):

  • bytecompiler/BytecodeGenerator.h:
  • dfg/DFGAbstractInterpreterInlines.h:

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

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasIdentifier):

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileResolveScopeForHoistingFuncDeclInEval):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileResolveScopeForHoistingFuncDeclInEval):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::execute):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITOperations.h:
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_resolve_scope_for_hoisting_func_decl_in_eval):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emit_op_resolve_scope_for_hoisting_func_decl_in_eval):

  • llint/LowLevelInterpreter.asm:
  • parser/Parser.cpp:

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

  • parser/Parser.h:

(JSC::Scope::getSloppyModeHoistedFunctions):
(JSC::Parser::declareFunction):

  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/CommonSlowPaths.h:
  • runtime/EvalExecutable.h:

(JSC::EvalExecutable::numFunctionHoistingCandidates):
(JSC::EvalExecutable::numTopLevelFunctionDecls):
(JSC::EvalExecutable::numberOfFunctionDecls): Deleted.

  • runtime/JSScope.cpp:

(JSC::JSScope::resolve):
(JSC::JSScope::resolveScopeForHoistingFuncDeclInEval):

  • runtime/JSScope.h:

LayoutTests:

  • inspector/runtime/evaluate-CommandLineAPI-expected.txt:
  • inspector/runtime/evaluate-CommandLineAPI.html:
  • js/parser-syntax-check-expected.txt:
  • js/script-tests/parser-syntax-check.js:
Location:
trunk/Source/JavaScriptCore/jit
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r215779 r215984  
    393393
    394394        DEFINE_OP(op_resolve_scope)
     395        DEFINE_OP(op_resolve_scope_for_hoisting_func_decl_in_eval)
    395396        DEFINE_OP(op_get_from_scope)
    396397        DEFINE_OP(op_put_to_scope)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r215779 r215984  
    666666
    667667        void emit_op_resolve_scope(Instruction*);
     668        void emit_op_resolve_scope_for_hoisting_func_decl_in_eval(Instruction*);
    668669        void emit_op_get_from_scope(Instruction*);
    669670        void emit_op_put_to_scope(Instruction*);
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r215779 r215984  
    154154typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJMic)(ExecState*, EncodedJSValue, EncodedJSValue, void*);
    155155typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJMic)(ExecState*, EncodedJSValue, void*);
     156typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJscI)(ExecState*, JSScope*, UniquedStringImpl*);
    156157typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssZ)(ExecState*, JSString*, int32_t);
    157158typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJss)(ExecState*, JSString*);
     
    233234typedef int32_t (JIT_OPERATION *Z_JITOperation_EOI)(ExecState*, JSObject*, UniquedStringImpl*);
    234235typedef int32_t (JIT_OPERATION *Z_JITOperation_EOJ)(ExecState*, JSObject*, EncodedJSValue);
     236typedef size_t (JIT_OPERATION *S_JITOperation_EO)(ExecState*, JSObject*);
    235237typedef size_t (JIT_OPERATION *S_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
    236238typedef size_t (JIT_OPERATION *S_JITOperation_EGC)(ExecState*, JSGlobalObject*, JSCell*);
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r215779 r215984  
    763763        loadPtr(Address(regT0, JSScope::offsetOfNext()), regT0);
    764764    emitPutVirtualRegister(dst);
     765}
     766
     767void JIT::emit_op_resolve_scope_for_hoisting_func_decl_in_eval(Instruction* currentInstruction)
     768{
     769    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_resolve_scope_for_hoisting_func_decl_in_eval);
     770    slowPathCall.call();
    765771}
    766772
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r215779 r215984  
    772772}
    773773
     774void JIT::emit_op_resolve_scope_for_hoisting_func_decl_in_eval(Instruction* currentInstruction)
     775{
     776    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_resolve_scope_for_hoisting_func_decl_in_eval);
     777    slowPathCall.call();
     778}
     779   
    774780void JIT::emit_op_resolve_scope(Instruction* currentInstruction)
    775781{
Note: See TracChangeset for help on using the changeset viewer.