12017-03-20 Oleksandr Skachkov <gskachkov@gmail.com>
2
3 [ES6]. Implement Annex B.3.3 function hoisting rules for eval
4 https://bugs.webkit.org/show_bug.cgi?id=163208
5
6 Reviewed by NOBODY (OOPS!).
7
8 Current patch implements Annex B.3.3 that is related to
9 hoisting of function declaration in eval.
10 https://tc39.github.io/ecma262/#sec-web-compat-evaldeclarationinstantiation
11 Function declaration in eval should create variable with
12 function name in function scope where eval is invoked
13 or bind to variable if it declared outside of the eval.
14 If variable is created it can be removed by 'delete a;' command.
15 If eval is invoke in block scope that contains let/const
16 variable with the same name as function declaration
17 we do not bind. This patch leads to the following behavior:
18 '''
19 function foo() {
20 {
21 print(boo); // undefined
22 eval('{ function boo() {}}');
23 print(boo); // function boo() {}
24 }
25 print(boo); // function boo() {}
26 }
27
28 function foobar() {
29 {
30 let boo = 10;
31 print(boo); // 10;
32 eval('{ function boo() {}}');
33 print(boo); // 10;
34 }
35 print(boo) // 10
36 }
37
38 function bar() {
39 {
40 var boo = 10;
41 print(boo); // 10
42 eval('{ function boo() {} }');
43 print(boo); // function boo() {}
44 }
45 print(boo); // function boo() {}
46 }
47
48 function bas() {
49 {
50 let boo = 10;
51 eval(' { function boo() {} } ');
52 print(boo); // 10
53 }
54 print(boo); //Reference Error
55 }
56 '''
57
58 Current implementation relies on already implemented
59 'hoist function in sloppy mode' feature, with small changes.
60 In short it works in following way: during hoisting of function
61 with name S in eval, we are looking for first scope that
62 contains space for variable with name S and if this scope
63 has var type we bind function there
64
65 To implement this feature was added bytecode ops:
66 op_resolve_scope_for_hoisting_func_decl_in_eval - get variable scope
67 or return undefined if variable can't be binded there.
68
69 There is a corner case, hoist function in eval within catch block,
70 that is not covered by this patch, and will be fixed in
71 https://bugs.webkit.org/show_bug.cgi?id=168184
72
73 * bytecode/BytecodeList.json:
74 * bytecode/BytecodeUseDef.h:
75 (JSC::computeUsesForBytecodeOffset):
76 (JSC::computeDefsForBytecodeOffset):
77 * bytecode/CodeBlock.cpp:
78 (JSC::CodeBlock::finalizeLLIntInlineCaches):
79 * bytecode/EvalCodeBlock.h:
80 (JSC::EvalCodeBlock::codeBlockFunction):
81 (JSC::EvalCodeBlock::numCodeBlockFunctionDecls):
82 * bytecode/UnlinkedEvalCodeBlock.h:
83 * bytecompiler/BytecodeGenerator.cpp:
84 (JSC::BytecodeGenerator::BytecodeGenerator):
85 (JSC::BytecodeGenerator::hoistSloppyModeFunctionIfNecessary):
86 (JSC::BytecodeGenerator::emitResolveScopeForHoistingFuncDeclInEval):
87 * bytecompiler/BytecodeGenerator.h:
88 * dfg/DFGAbstractInterpreterInlines.h:
89 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
90 * dfg/DFGByteCodeParser.cpp:
91 (JSC::DFG::ByteCodeParser::parseBlock):
92 * dfg/DFGCapabilities.cpp:
93 (JSC::DFG::capabilityLevel):
94 * dfg/DFGClobberize.h:
95 (JSC::DFG::clobberize):
96 * dfg/DFGDoesGC.cpp:
97 (JSC::DFG::doesGC):
98 * dfg/DFGFixupPhase.cpp:
99 (JSC::DFG::FixupPhase::fixupNode):
100 * dfg/DFGNode.h:
101 (JSC::DFG::Node::hasIdentifier):
102 * dfg/DFGNodeType.h:
103 * dfg/DFGOperations.cpp:
104 * dfg/DFGOperations.h:
105 * dfg/DFGPredictionPropagationPhase.cpp:
106 * dfg/DFGSafeToExecute.h:
107 (JSC::DFG::safeToExecute):
108 * dfg/DFGSpeculativeJIT.cpp:
109 (JSC::DFG::SpeculativeJIT::compileResolveScopeForHoistingFuncDeclInEval):
110 * dfg/DFGSpeculativeJIT.h:
111 (JSC::DFG::SpeculativeJIT::callOperation):
112 * dfg/DFGSpeculativeJIT32_64.cpp:
113 (JSC::DFG::SpeculativeJIT::compile):
114 * dfg/DFGSpeculativeJIT64.cpp:
115 (JSC::DFG::SpeculativeJIT::compile):
116 * ftl/FTLCapabilities.cpp:
117 (JSC::FTL::canCompile):
118 * ftl/FTLLowerDFGToB3.cpp:
119 (JSC::FTL::DFG::LowerDFGToB3::compileNode):
120 (JSC::FTL::DFG::LowerDFGToB3::compileResolveScopeForHoistingFuncDeclInEval):
121 * interpreter/Interpreter.cpp:
122 (JSC::Interpreter::execute):
123 * jit/JIT.cpp:
124 (JSC::JIT::privateCompileMainPass):
125 * jit/JIT.h:
126 * jit/JITOperations.h:
127 * jit/JITPropertyAccess.cpp:
128 (JSC::JIT::emitResolveClosure):
129 (JSC::JIT::emit_op_resolve_scope_for_hoisting_func_decl_in_eval):
130 * jit/JITPropertyAccess32_64.cpp:
131 (JSC::JIT::emit_op_resolve_scope_for_hoisting_func_decl_in_eval):
132 * llint/LowLevelInterpreter.asm:
133 * parser/Parser.cpp:
134 (JSC::Parser<LexerType>::parseFunctionDeclarationStatement):
135 * parser/Parser.h:
136 (JSC::Scope::getSloppyModeHoistedFunctions):
137 (JSC::Parser::declareFunction):
138 * runtime/CommonSlowPaths.cpp:
139 (JSC::SLOW_PATH_DECL):
140 * runtime/CommonSlowPaths.h:
141 * runtime/EvalExecutable.h:
142 (JSC::EvalExecutable::numCodeBlockFunctionDecls):
143 (JSC::EvalExecutable::numTopLevelFunctionDecls):
144 * runtime/JSScope.cpp:
145 (JSC::JSScope::resolve):
146 (JSC::JSScope::resolveScopeForHoistingFuncDeclInEval):
147 * runtime/JSScope.h:
148